From c33d24251a57433abec9a53fd2643aa92883e419 Mon Sep 17 00:00:00 2001 From: bogdan-rosianu Date: Mon, 25 Nov 2024 17:09:05 +0200 Subject: [PATCH 01/12] API-98: relayed v3 transactions support --- src/common/gateway/entities/transaction.ts | 2 ++ .../indexer/elastic/elastic.indexer.helper.ts | 4 ++++ .../transactions/entities/transaction.ts | 3 +++ .../transactions/transaction.controller.ts | 15 ++++++++++++++- .../transactions/transaction.get.service.ts | 2 ++ 5 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/common/gateway/entities/transaction.ts b/src/common/gateway/entities/transaction.ts index 834617864..47e671142 100644 --- a/src/common/gateway/entities/transaction.ts +++ b/src/common/gateway/entities/transaction.ts @@ -43,4 +43,6 @@ export class Transaction { logs: TransactionLog | undefined = undefined; receipt: TransactionReceipt | undefined = undefined; smartContractResults: GatewaySmartContractResults[] | undefined = undefined; + relayerAddress: string = ''; + relayerSignature: string = ''; } diff --git a/src/common/indexer/elastic/elastic.indexer.helper.ts b/src/common/indexer/elastic/elastic.indexer.helper.ts index be10ff0a9..583a6eb8d 100644 --- a/src/common/indexer/elastic/elastic.indexer.helper.ts +++ b/src/common/indexer/elastic/elastic.indexer.helper.ts @@ -535,6 +535,10 @@ export class ElasticIndexerHelper { elasticQuery = elasticQuery.withMustMatchCondition('isRelayed', filter.isRelayed); } + if (filter.relayer) { + elasticQuery = elasticQuery.withShouldCondition(QueryType.Match('relayer', filter.relayer)); + } + if (filter.round) { elasticQuery = elasticQuery.withMustMatchCondition('round', filter.round); } diff --git a/src/endpoints/transactions/entities/transaction.ts b/src/endpoints/transactions/entities/transaction.ts index 9eed2dd2f..b8e284733 100644 --- a/src/endpoints/transactions/entities/transaction.ts +++ b/src/endpoints/transactions/entities/transaction.ts @@ -107,6 +107,9 @@ export class Transaction { @ApiProperty({ type: String, nullable: true, required: false }) relayer: string | undefined = undefined; + @ApiProperty({ type: String, nullable: true, required: false }) + relayerSignature: string | undefined = undefined; + getDate(): Date | undefined { if (this.timestamp) { return new Date(this.timestamp * 1000); diff --git a/src/endpoints/transactions/transaction.controller.ts b/src/endpoints/transactions/transaction.controller.ts index 5342002e8..f8491b6dc 100644 --- a/src/endpoints/transactions/transaction.controller.ts +++ b/src/endpoints/transactions/transaction.controller.ts @@ -1,5 +1,16 @@ import { QueryConditionOptions } from '@multiversx/sdk-nestjs-elastic'; -import { ParseBlockHashPipe, ParseBoolPipe, ParseEnumPipe, ParseIntPipe, ParseTransactionHashPipe, ParseAddressAndMetachainPipe, ApplyComplexity, ParseAddressArrayPipe, ParseArrayPipe } from '@multiversx/sdk-nestjs-common'; +import { + ParseBlockHashPipe, + ParseBoolPipe, + ParseEnumPipe, + ParseIntPipe, + ParseTransactionHashPipe, + ParseAddressAndMetachainPipe, + ApplyComplexity, + ParseAddressArrayPipe, + ParseArrayPipe, + ParseAddressPipe, +} from '@multiversx/sdk-nestjs-common'; import { BadRequestException, Body, Controller, DefaultValuePipe, Get, NotFoundException, Param, Post, Query } from '@nestjs/common'; import { ApiCreatedResponse, ApiExcludeEndpoint, ApiNotFoundResponse, ApiOkResponse, ApiOperation, ApiQuery, ApiTags } from '@nestjs/swagger'; import { QueryPagination } from 'src/common/entities/query.pagination'; @@ -54,6 +65,7 @@ export class TransactionController { @Query('size', new DefaultValuePipe(25), ParseIntPipe) size: number, @Query('sender', ParseAddressAndMetachainPipe) sender?: string, @Query('receiver', ParseAddressArrayPipe) receiver?: string[], + @Query('relayer', ParseAddressPipe) relayer?: string, @Query('token') token?: string, @Query('senderShard', ParseIntPipe) senderShard?: number, @Query('receiverShard', ParseIntPipe) receiverShard?: number, @@ -81,6 +93,7 @@ export class TransactionController { return this.transactionService.getTransactions(new TransactionFilter({ sender, receivers: receiver, + relayer, token, functions, senderShard, diff --git a/src/endpoints/transactions/transaction.get.service.ts b/src/endpoints/transactions/transaction.get.service.ts index ac2b8afb5..1d098539d 100644 --- a/src/endpoints/transactions/transaction.get.service.ts +++ b/src/endpoints/transactions/transaction.get.service.ts @@ -250,6 +250,8 @@ export class TransactionGetService { guardianAddress: transaction.guardian, guardianSignature: transaction.guardianSignature, inTransit: transaction.miniblockHash !== undefined && transaction.status === TransactionStatus.pending, + relayer: transaction.relayerAddress, + relayerSignature: transaction.relayerSignature, }; return ApiUtils.mergeObjects(new TransactionDetailed(), result); From 6d75e072e6785d06d609614dfd171e446da6068d Mon Sep 17 00:00:00 2001 From: bogdan-rosianu Date: Tue, 26 Nov 2024 13:56:10 +0200 Subject: [PATCH 02/12] added missing filters --- src/endpoints/transactions/transaction.controller.ts | 8 +++++++- src/endpoints/transfers/transfer.controller.ts | 7 +++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/endpoints/transactions/transaction.controller.ts b/src/endpoints/transactions/transaction.controller.ts index f8491b6dc..02a5b2cf7 100644 --- a/src/endpoints/transactions/transaction.controller.ts +++ b/src/endpoints/transactions/transaction.controller.ts @@ -58,6 +58,7 @@ export class TransactionController { @ApiQuery({ name: 'withScamInfo', description: 'Returns scam information', required: false, type: Boolean }) @ApiQuery({ name: 'withUsername', description: 'Integrates username in assets for all addresses present in the transactions', required: false, type: Boolean }) @ApiQuery({ name: 'withBlockInfo', description: 'Returns sender / receiver block details', required: false, type: Boolean }) + @ApiQuery({ name: 'relayer', description: 'Search by a relayer address', required: false }) @ApiQuery({ name: 'isRelayed', description: 'Returns relayed transactions details', required: false, type: Boolean }) @ApiQuery({ name: 'withActionTransferValue', description: 'Returns value in USD and EGLD for transferred tokens within the action attribute', required: false }) getTransactions( @@ -93,7 +94,6 @@ export class TransactionController { return this.transactionService.getTransactions(new TransactionFilter({ sender, receivers: receiver, - relayer, token, functions, senderShard, @@ -105,6 +105,7 @@ export class TransactionController { after, condition, order, + relayer, isRelayed, round, }), @@ -132,6 +133,7 @@ export class TransactionController { @ApiQuery({ name: 'after', description: 'After timestamp', required: false }) @ApiQuery({ name: 'round', description: 'Round number', required: false }) @ApiQuery({ name: 'isRelayed', description: 'Returns relayed transactions details', required: false, type: Boolean }) + @ApiQuery({ name: 'relayer', description: 'Filter by a relayer address', required: false }) getTransactionCount( @Query('sender', ParseAddressAndMetachainPipe) sender?: string, @Query('receiver', ParseAddressArrayPipe) receiver?: string[], @@ -146,6 +148,7 @@ export class TransactionController { @Query('before', ParseIntPipe) before?: number, @Query('after', ParseIntPipe) after?: number, @Query('round', ParseIntPipe) round?: number, + @Query('relaer', new ParseAddressPipe()) relayer?: string, @Query('isRelayed', new ParseBoolPipe) isRelayed?: boolean, ): Promise { return this.transactionService.getTransactionCount(new TransactionFilter({ @@ -161,6 +164,7 @@ export class TransactionController { before, after, condition, + relayer, isRelayed, round, })); @@ -182,6 +186,7 @@ export class TransactionController { @Query('before', ParseIntPipe) before?: number, @Query('after', ParseIntPipe) after?: number, @Query('round', new ParseIntPipe) round?: number, + @Query('relayer', new ParseAddressPipe()) relayer?: string, @Query('isRelayed', new ParseBoolPipe) isRelayed?: boolean, ): Promise { return this.transactionService.getTransactionCount(new TransactionFilter({ @@ -198,6 +203,7 @@ export class TransactionController { after, condition, isRelayed, + relayer, round, })); } diff --git a/src/endpoints/transfers/transfer.controller.ts b/src/endpoints/transfers/transfer.controller.ts index ca2c4622b..c1b038e51 100644 --- a/src/endpoints/transfers/transfer.controller.ts +++ b/src/endpoints/transfers/transfer.controller.ts @@ -114,6 +114,7 @@ export class TransferController { @ApiQuery({ name: 'before', description: 'Before timestamp', required: false }) @ApiQuery({ name: 'after', description: 'After timestamp', required: false }) @ApiQuery({ name: 'round', description: 'Round number', required: false }) + @ApiQuery({ name: 'relayer', description: 'Filter by the relayer address', required: false }) @ApiQuery({ name: 'isRelayed', description: 'Returns relayed transactions details', required: false, type: Boolean }) async getAccountTransfersCount( @Query('sender', ParseAddressArrayPipe) sender?: string[], @@ -128,6 +129,7 @@ export class TransferController { @Query('before', ParseIntPipe) before?: number, @Query('after', ParseIntPipe) after?: number, @Query('round', ParseIntPipe) round?: number, + @Query('relayer', ParseAddressPipe) relayer?: string, @Query('isRelayed', new ParseBoolPipe) isRelayed?: boolean, ): Promise { return await this.transferService.getTransfersCount(new TransactionFilter({ @@ -142,6 +144,7 @@ export class TransferController { status, before, after, + relayer, isRelayed, round, })); @@ -162,6 +165,8 @@ export class TransferController { @Query('before', ParseIntPipe) before?: number, @Query('after', ParseIntPipe) after?: number, @Query('round', ParseIntPipe) round?: number, + @Query('relayer', ParseAddressPipe) relayer?: string, + @Query('isRelayed', new ParseBoolPipe) isRelayed?: boolean, ): Promise { return await this.transferService.getTransfersCount(new TransactionFilter({ senders: sender, @@ -176,6 +181,8 @@ export class TransferController { before, after, round, + relayer, + isRelayed, })); } } From 2a2de246cbb4b8604137d9bbd723a452bf615fd8 Mon Sep 17 00:00:00 2001 From: bogdan-rosianu Date: Wed, 27 Nov 2024 14:43:08 +0200 Subject: [PATCH 03/12] fixes after review --- src/endpoints/transactions/transaction.controller.ts | 8 ++++---- src/endpoints/transfers/transfer.controller.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/endpoints/transactions/transaction.controller.ts b/src/endpoints/transactions/transaction.controller.ts index 02a5b2cf7..223a6b6b3 100644 --- a/src/endpoints/transactions/transaction.controller.ts +++ b/src/endpoints/transactions/transaction.controller.ts @@ -148,8 +148,8 @@ export class TransactionController { @Query('before', ParseIntPipe) before?: number, @Query('after', ParseIntPipe) after?: number, @Query('round', ParseIntPipe) round?: number, - @Query('relaer', new ParseAddressPipe()) relayer?: string, - @Query('isRelayed', new ParseBoolPipe) isRelayed?: boolean, + @Query('relayer', ParseAddressPipe) relayer?: string, + @Query('isRelayed', ParseBoolPipe) isRelayed?: boolean, ): Promise { return this.transactionService.getTransactionCount(new TransactionFilter({ sender, @@ -186,8 +186,8 @@ export class TransactionController { @Query('before', ParseIntPipe) before?: number, @Query('after', ParseIntPipe) after?: number, @Query('round', new ParseIntPipe) round?: number, - @Query('relayer', new ParseAddressPipe()) relayer?: string, - @Query('isRelayed', new ParseBoolPipe) isRelayed?: boolean, + @Query('relayer', ParseAddressPipe) relayer?: string, + @Query('isRelayed', ParseBoolPipe) isRelayed?: boolean, ): Promise { return this.transactionService.getTransactionCount(new TransactionFilter({ sender, diff --git a/src/endpoints/transfers/transfer.controller.ts b/src/endpoints/transfers/transfer.controller.ts index c1b038e51..d37063d7b 100644 --- a/src/endpoints/transfers/transfer.controller.ts +++ b/src/endpoints/transfers/transfer.controller.ts @@ -166,7 +166,7 @@ export class TransferController { @Query('after', ParseIntPipe) after?: number, @Query('round', ParseIntPipe) round?: number, @Query('relayer', ParseAddressPipe) relayer?: string, - @Query('isRelayed', new ParseBoolPipe) isRelayed?: boolean, + @Query('isRelayed', ParseBoolPipe) isRelayed?: boolean, ): Promise { return await this.transferService.getTransfersCount(new TransactionFilter({ senders: sender, From 50f2d0b79fc42854e35cd9a84a708cc13f0c33fd Mon Sep 17 00:00:00 2001 From: bogdan-rosianu Date: Fri, 10 Jan 2025 14:18:45 +0200 Subject: [PATCH 04/12] fixes after merge --- src/endpoints/transactions/transaction.controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/endpoints/transactions/transaction.controller.ts b/src/endpoints/transactions/transaction.controller.ts index a447d0425..aa0bbbb15 100644 --- a/src/endpoints/transactions/transaction.controller.ts +++ b/src/endpoints/transactions/transaction.controller.ts @@ -1,5 +1,5 @@ import { QueryConditionOptions } from '@multiversx/sdk-nestjs-elastic'; -import { ParseBlockHashPipe, ParseBoolPipe, ParseEnumPipe, ParseIntPipe, ParseTransactionHashPipe, ParseAddressAndMetachainPipe, ApplyComplexity, ParseAddressArrayPipe, ParseArrayPipe } from '@multiversx/sdk-nestjs-common'; +import { ParseBlockHashPipe, ParseBoolPipe, ParseEnumPipe, ParseIntPipe, ParseTransactionHashPipe, ParseAddressAndMetachainPipe, ApplyComplexity, ParseAddressArrayPipe, ParseArrayPipe, ParseAddressPipe } from '@multiversx/sdk-nestjs-common'; import { BadRequestException, Body, Controller, DefaultValuePipe, Get, NotFoundException, Param, Post, Query } from '@nestjs/common'; import { ApiCreatedResponse, ApiExcludeEndpoint, ApiNotFoundResponse, ApiOkResponse, ApiOperation, ApiQuery, ApiTags } from '@nestjs/swagger'; import { QueryPagination } from 'src/common/entities/query.pagination'; From 7dace6cfa290da75f981388a44b21459bda1ee46 Mon Sep 17 00:00:00 2001 From: bogdan-rosianu Date: Fri, 10 Jan 2025 16:17:13 +0200 Subject: [PATCH 05/12] added filter to fetch transfers where an address is relayer --- .../indexer/elastic/elastic.indexer.helper.ts | 16 +++++++++++----- src/common/indexer/entities/transaction.ts | 3 +++ src/endpoints/accounts/account.controller.ts | 5 ++++- .../transactions/entities/transaction.filter.ts | 1 + src/endpoints/transfers/transfer.service.ts | 7 ++++++- 5 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/common/indexer/elastic/elastic.indexer.helper.ts b/src/common/indexer/elastic/elastic.indexer.helper.ts index 8a222f602..5d879d190 100644 --- a/src/common/indexer/elastic/elastic.indexer.helper.ts +++ b/src/common/indexer/elastic/elastic.indexer.helper.ts @@ -316,17 +316,23 @@ export class ElasticIndexerHelper { if (filter.withRefunds) { mustNotQueries = []; } + + const shouldConditions = [ + QueryType.Match('sender', filter.address), + QueryType.Match('receiver', filter.address), + QueryType.Match('receivers', filter.address), + ]; + if (filter.withTxsRelayedByAddress) { + shouldConditions.push(QueryType.Match('relayer', filter.address)); + } + elasticQuery = elasticQuery.withCondition(QueryConditionOptions.should, QueryType.Must([ QueryType.Match('type', 'unsigned'), QueryType.Should(smartContractResultConditions), ], mustNotQueries)) .withCondition(QueryConditionOptions.should, QueryType.Must([ QueryType.Should([QueryType.Match('type', 'normal')]), - QueryType.Should([ - QueryType.Match('sender', filter.address), - QueryType.Match('receiver', filter.address), - QueryType.Match('receivers', filter.address), - ]), + QueryType.Should(shouldConditions), ])); } diff --git a/src/common/indexer/entities/transaction.ts b/src/common/indexer/entities/transaction.ts index a34573bca..e93095bd3 100644 --- a/src/common/indexer/entities/transaction.ts +++ b/src/common/indexer/entities/transaction.ts @@ -31,4 +31,7 @@ export interface Transaction { scResults: any[]; version: number; relayerAddr: string; + relayer: string; + relayerSignature: string; + isRelayed: boolean; } diff --git a/src/endpoints/accounts/account.controller.ts b/src/endpoints/accounts/account.controller.ts index 38fd1b17d..979378ecf 100644 --- a/src/endpoints/accounts/account.controller.ts +++ b/src/endpoints/accounts/account.controller.ts @@ -1018,6 +1018,7 @@ export class AccountController { @ApiQuery({ name: 'withOperations', description: 'Return operations for transfers. When "withOperations" parameter is applied, complexity estimation is 200', required: false }) @ApiQuery({ name: 'withActionTransferValue', description: 'Returns value in USD and EGLD for transferred tokens within the action attribute', required: false }) @ApiQuery({ name: 'withRefunds', description: 'Include refund transactions', required: false }) + @ApiQuery({ name: 'withTxsRelayedByAddress', description: 'Include transactions that were relayed by the address', required: false }) async getAccountTransfers( @Param('address', ParseAddressPipe) address: string, @Query('from', new DefaultValuePipe(0), ParseIntPipe) from: number, @@ -1045,6 +1046,7 @@ export class AccountController { @Query('withOperations', ParseBoolPipe) withOperations?: boolean, @Query('withActionTransferValue', ParseBoolPipe) withActionTransferValue?: boolean, @Query('withRefunds', ParseBoolPipe) withRefunds?: boolean, + @Query('withTxsRelayedByAddress', ParseBoolPipe) withTxsRelayedByAddress?: boolean, ): Promise { const options = TransactionQueryOptions.applyDefaultOptions( size, { withScamInfo, withUsername, withBlockInfo, withOperations, withLogs, withActionTransferValue }); @@ -1067,6 +1069,7 @@ export class AccountController { relayer, round, withRefunds, + withTxsRelayedByAddress, }), new QueryPagination({ from, size }), options, @@ -1075,7 +1078,7 @@ export class AccountController { } @Get("/accounts/:address/transfers/count") - @ApiOperation({ summary: 'Account transfer count', description: 'Return total count of tranfers triggerred by a user account (type = Transaction), as well as transfers triggerred by smart contracts (type = SmartContractResult)' }) + @ApiOperation({ summary: 'Account transfer count', description: 'Return total count of transfers triggerred by a user account (type = Transaction), as well as transfers triggerred by smart contracts (type = SmartContractResult)' }) @ApiOkResponse({ type: Number }) @ApiQuery({ name: 'sender', description: 'Address of the transfer sender', required: false }) @ApiQuery({ name: 'receiver', description: 'Search by multiple receiver addresses, comma-separated', required: false }) diff --git a/src/endpoints/transactions/entities/transaction.filter.ts b/src/endpoints/transactions/entities/transaction.filter.ts index 5462a0822..e20cc08bb 100644 --- a/src/endpoints/transactions/entities/transaction.filter.ts +++ b/src/endpoints/transactions/entities/transaction.filter.ts @@ -28,6 +28,7 @@ export class TransactionFilter { round?: number; withRefunds?: boolean; withRelayedScresults?: boolean; + withTxsRelayedByAddress?: boolean; constructor(init?: Partial) { Object.assign(this, init); diff --git a/src/endpoints/transfers/transfer.service.ts b/src/endpoints/transfers/transfer.service.ts index 4ec698e2a..acb73e031 100644 --- a/src/endpoints/transfers/transfer.service.ts +++ b/src/endpoints/transfers/transfer.service.ts @@ -51,7 +51,12 @@ export class TransferService { for (const elasticOperation of elasticOperations) { const transaction = ApiUtils.mergeObjects(new TransactionDetailed(), elasticOperation); transaction.type = elasticOperation.type === 'normal' ? TransactionType.Transaction : TransactionType.SmartContractResult; - transaction.relayer = elasticOperation.relayerAddr; + if (elasticOperation.relayer) { + transaction.relayer = elasticOperation.relayer; + transaction.isRelayed = true; + } else { + transaction.relayer = elasticOperation.relayerAddr; + } if (transaction.type === TransactionType.SmartContractResult) { delete transaction.gasLimit; From 20330047679095b3337231a6d6220fe5fd3a9ace Mon Sep 17 00:00:00 2001 From: bogdan-rosianu Date: Fri, 10 Jan 2025 16:51:57 +0200 Subject: [PATCH 06/12] fix unit tests --- src/test/unit/services/accounts.spec.ts | 3 +++ src/test/unit/services/transactions.spec.ts | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/src/test/unit/services/accounts.spec.ts b/src/test/unit/services/accounts.spec.ts index 31e3026e0..6893f7032 100644 --- a/src/test/unit/services/accounts.spec.ts +++ b/src/test/unit/services/accounts.spec.ts @@ -427,6 +427,9 @@ describe('Account Service', () => { scResults: [], relayerAddr: '', version: 2, + relayer: '', + isRelayed: false, + relayerSignature: '', }); const result = await service.getAccountDeployedAtRaw(address); diff --git a/src/test/unit/services/transactions.spec.ts b/src/test/unit/services/transactions.spec.ts index de5d635b8..5dbb87039 100644 --- a/src/test/unit/services/transactions.spec.ts +++ b/src/test/unit/services/transactions.spec.ts @@ -185,6 +185,9 @@ describe('TransactionService', () => { scResults: [''], relayerAddr: 'erd1sdrjn0uuulydacwjam3v5afl427ptk797fpcujpfcsakfck8aqjquq9afc', version: 1, + relayer: 'erd1sdrjn0uuulydacwjam3v5afl427ptk797fpcujpfcsakfck8aqjquq9afc', + isRelayed: true, + relayerSignature: 'bc51e9032332740d60c404d4bf553ae225ca77a70ad799a1cdfc6e73609be8ec62e89ac6e2c2621ffbfb89e6fab620c137010662f3ebea9c422c9f1dbec04a03', }, { hash: '2b1ce5558f5faa533afd437a42a5aeadea8302dc3cca778c0ed50d19c0a047a4', @@ -222,6 +225,9 @@ describe('TransactionService', () => { scResults: [''], relayerAddr: 'erd1sdrjn0uuulydacwjam3v5afl427ptk797fpcujpfcsakfck8aqjquq9afc', version: 1, + relayer: 'erd1sdrjn0uuulydacwjam3v5afl427ptk797fpcujpfcsakfck8aqjquq9afc', + isRelayed: true, + relayerSignature: 'bc51e9032332740d60c404d4bf553ae225ca77a70ad799a1cdfc6e73609be8ec62e89ac6e2c2621ffbfb89e6fab620c137010662f3ebea9c422c9f1dbec04a03', }, ]; From f54028377cd66f381d6a2fd3e3837f505cc71e57 Mon Sep 17 00:00:00 2001 From: bogdan-rosianu Date: Fri, 10 Jan 2025 17:21:48 +0200 Subject: [PATCH 07/12] added checks for multiple fields when getting transaction with isRelayed true --- src/common/indexer/elastic/elastic.indexer.helper.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/common/indexer/elastic/elastic.indexer.helper.ts b/src/common/indexer/elastic/elastic.indexer.helper.ts index 5d879d190..a67054e5a 100644 --- a/src/common/indexer/elastic/elastic.indexer.helper.ts +++ b/src/common/indexer/elastic/elastic.indexer.helper.ts @@ -341,7 +341,10 @@ export class ElasticIndexerHelper { } if (filter.isRelayed) { - elasticQuery = elasticQuery.withMustMatchCondition('isRelayed', filter.isRelayed); + elasticQuery = elasticQuery.withMustCondition(QueryType.Should([ + QueryType.Match('isRelayed', filter.isRelayed), + QueryType.Exists('relayer'), + ])); } if (filter.type) { @@ -556,7 +559,10 @@ export class ElasticIndexerHelper { } if (filter.isRelayed) { - elasticQuery = elasticQuery.withMustMatchCondition('isRelayed', filter.isRelayed); + elasticQuery = elasticQuery.withMustCondition(QueryType.Should([ + QueryType.Match('isRelayed', filter.isRelayed), + QueryType.Exists('relayer'), + ])); } if (filter.relayer) { From dac048f90a260c8b83fe71a8069f2902a8776f16 Mon Sep 17 00:00:00 2001 From: bogdan-rosianu Date: Mon, 13 Jan 2025 11:28:41 +0200 Subject: [PATCH 08/12] extract v3 version --- src/endpoints/transactions/transaction.service.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/endpoints/transactions/transaction.service.ts b/src/endpoints/transactions/transaction.service.ts index 16b9cb021..05ed4f306 100644 --- a/src/endpoints/transactions/transaction.service.ts +++ b/src/endpoints/transactions/transaction.service.ts @@ -559,6 +559,8 @@ export class TransactionService { return 'v1'; } else if (decodedData.startsWith('relayedTxV2@')) { return 'v2'; + } else if (transaction.relayer) { + return 'v3'; } } From 784dac574c858bf185ac11f436cf4f9a90f80de0 Mon Sep 17 00:00:00 2001 From: bogdan-rosianu Date: Mon, 13 Jan 2025 11:39:57 +0200 Subject: [PATCH 09/12] fix relayed version extractor --- src/endpoints/transactions/transaction.service.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/endpoints/transactions/transaction.service.ts b/src/endpoints/transactions/transaction.service.ts index 05ed4f306..7b0bcfb6d 100644 --- a/src/endpoints/transactions/transaction.service.ts +++ b/src/endpoints/transactions/transaction.service.ts @@ -559,11 +559,13 @@ export class TransactionService { return 'v1'; } else if (decodedData.startsWith('relayedTxV2@')) { return 'v2'; - } else if (transaction.relayer) { - return 'v3'; } } + if (transaction.relayer) { + return 'v3'; + } + return undefined; } } From 15d686b48d414f088391e8649d73a46e0e3e52c6 Mon Sep 17 00:00:00 2001 From: bogdan-rosianu Date: Fri, 17 Jan 2025 10:25:29 +0200 Subject: [PATCH 10/12] include relayedVersion field in single tx fetching --- src/endpoints/transactions/transaction.service.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/endpoints/transactions/transaction.service.ts b/src/endpoints/transactions/transaction.service.ts index 7b0bcfb6d..3fb2770a9 100644 --- a/src/endpoints/transactions/transaction.service.ts +++ b/src/endpoints/transactions/transaction.service.ts @@ -210,6 +210,7 @@ export class TransactionService { if (transaction !== null) { transaction.price = await this.getTransactionPrice(transaction); + transaction.relayedVersion = this.extractRelayedVersion(transaction); await this.processTransactions([transaction], { withScamInfo: true, withUsername: true, withActionTransferValue }); From e58959abc28196f8fcf0f2c608fd1f5c86c8680c Mon Sep 17 00:00:00 2001 From: bogdan-rosianu Date: Fri, 17 Jan 2025 11:30:26 +0200 Subject: [PATCH 11/12] exclude relayed txs if isRelayed=false --- .../indexer/elastic/elastic.indexer.helper.ts | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/common/indexer/elastic/elastic.indexer.helper.ts b/src/common/indexer/elastic/elastic.indexer.helper.ts index a67054e5a..b6b150f5d 100644 --- a/src/common/indexer/elastic/elastic.indexer.helper.ts +++ b/src/common/indexer/elastic/elastic.indexer.helper.ts @@ -340,11 +340,14 @@ export class ElasticIndexerHelper { elasticQuery = elasticQuery.withMustMatchCondition('relayerAddr', filter.relayer); } - if (filter.isRelayed) { - elasticQuery = elasticQuery.withMustCondition(QueryType.Should([ - QueryType.Match('isRelayed', filter.isRelayed), - QueryType.Exists('relayer'), - ])); + const relayedConditions = QueryType.Should([ + QueryType.Match('isRelayed', filter.isRelayed), + QueryType.Exists('relayer'), + ]); + if (filter.isRelayed === true) { + elasticQuery = elasticQuery.withMustCondition(relayedConditions); + } else if (filter.isRelayed === false){ + elasticQuery = elasticQuery.withMustNotCondition(relayedConditions); } if (filter.type) { @@ -558,11 +561,14 @@ export class ElasticIndexerHelper { elasticQuery = elasticQuery.withMustMatchCondition('tokens', filter.token, QueryOperator.AND); } - if (filter.isRelayed) { - elasticQuery = elasticQuery.withMustCondition(QueryType.Should([ - QueryType.Match('isRelayed', filter.isRelayed), - QueryType.Exists('relayer'), - ])); + const relayedConditions = QueryType.Should([ + QueryType.Match('isRelayed', filter.isRelayed), + QueryType.Exists('relayer'), + ]); + if (filter.isRelayed === true) { + elasticQuery = elasticQuery.withMustCondition(relayedConditions); + } else if (filter.isRelayed === false){ + elasticQuery = elasticQuery.withMustNotCondition(relayedConditions); } if (filter.relayer) { From 227ff93f19013be4b81311d2ae1115df3d54ecff Mon Sep 17 00:00:00 2001 From: bogdan-rosianu Date: Fri, 17 Jan 2025 11:39:57 +0200 Subject: [PATCH 12/12] fix isRelayed query --- .../indexer/elastic/elastic.indexer.helper.ts | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/common/indexer/elastic/elastic.indexer.helper.ts b/src/common/indexer/elastic/elastic.indexer.helper.ts index b6b150f5d..0369f02f3 100644 --- a/src/common/indexer/elastic/elastic.indexer.helper.ts +++ b/src/common/indexer/elastic/elastic.indexer.helper.ts @@ -340,14 +340,16 @@ export class ElasticIndexerHelper { elasticQuery = elasticQuery.withMustMatchCondition('relayerAddr', filter.relayer); } - const relayedConditions = QueryType.Should([ - QueryType.Match('isRelayed', filter.isRelayed), - QueryType.Exists('relayer'), - ]); - if (filter.isRelayed === true) { - elasticQuery = elasticQuery.withMustCondition(relayedConditions); - } else if (filter.isRelayed === false){ - elasticQuery = elasticQuery.withMustNotCondition(relayedConditions); + if (filter.isRelayed !== undefined) { + const relayedConditions = QueryType.Should([ + QueryType.Match('isRelayed', true), + QueryType.Exists('relayer'), + ]); + if (filter.isRelayed === true) { + elasticQuery = elasticQuery.withMustCondition(relayedConditions); + } else if (filter.isRelayed === false) { + elasticQuery = elasticQuery.withMustNotCondition(relayedConditions); + } } if (filter.type) { @@ -561,14 +563,16 @@ export class ElasticIndexerHelper { elasticQuery = elasticQuery.withMustMatchCondition('tokens', filter.token, QueryOperator.AND); } - const relayedConditions = QueryType.Should([ - QueryType.Match('isRelayed', filter.isRelayed), - QueryType.Exists('relayer'), - ]); - if (filter.isRelayed === true) { - elasticQuery = elasticQuery.withMustCondition(relayedConditions); - } else if (filter.isRelayed === false){ - elasticQuery = elasticQuery.withMustNotCondition(relayedConditions); + if (filter.isRelayed !== undefined) { + const relayedConditions = QueryType.Should([ + QueryType.Match('isRelayed', true), + QueryType.Exists('relayer'), + ]); + if (filter.isRelayed === true) { + elasticQuery = elasticQuery.withMustCondition(relayedConditions); + } else if (filter.isRelayed === false) { + elasticQuery = elasticQuery.withMustNotCondition(relayedConditions); + } } if (filter.relayer) {