Skip to content

Commit

Permalink
Merge pull request #1442 from multiversx/development
Browse files Browse the repository at this point in the history
Development
  • Loading branch information
dragos-rebegea authored Jan 28, 2025
2 parents 914e3c9 + a541f0f commit 1d757c4
Show file tree
Hide file tree
Showing 15 changed files with 156 additions and 12 deletions.
2 changes: 2 additions & 0 deletions src/common/gateway/entities/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,6 @@ export class Transaction {
logs: TransactionLog | undefined = undefined;
receipt: TransactionReceipt | undefined = undefined;
smartContractResults: GatewaySmartContractResults[] | undefined = undefined;
relayerAddress: string = '';
relayerSignature: string = '';
}
1 change: 1 addition & 0 deletions src/common/gateway/gateway.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export class GatewayService {
GatewayComponentRequest.vmQuery,
GatewayComponentRequest.transactionPool,
GatewayComponentRequest.guardianData,
GatewayComponentRequest.validatorAuction,
]);

private readonly deepHistoryRequestsSet: Set<String> = new Set([
Expand Down
56 changes: 47 additions & 9 deletions src/common/indexer/elastic/elastic.indexer.helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -316,26 +316,40 @@ 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),
]));
}

if (filter.relayer) {
elasticQuery = elasticQuery.withMustMatchCondition('relayerAddr', filter.relayer);
}

if (filter.isRelayed) {
elasticQuery = elasticQuery.withMustMatchCondition('isRelayed', filter.isRelayed);
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) {
Expand Down Expand Up @@ -410,6 +424,12 @@ export class ElasticIndexerHelper {
elasticQuery = elasticQuery.withMustMatchCondition('round', filter.round);
}

if (filter.isScCall !== undefined) {
elasticQuery = filter.isScCall
? elasticQuery.withMustCondition(QueryType.Match('isScCall', true))
: elasticQuery.withMustNotCondition(QueryType.Match('isScCall', true));
}

return elasticQuery;
}

Expand Down Expand Up @@ -549,8 +569,20 @@ export class ElasticIndexerHelper {
elasticQuery = elasticQuery.withMustMatchCondition('tokens', filter.token, QueryOperator.AND);
}

if (filter.isRelayed) {
elasticQuery = elasticQuery.withMustMatchCondition('isRelayed', filter.isRelayed);
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) {
elasticQuery = elasticQuery.withShouldCondition(QueryType.Match('relayer', filter.relayer));
}

if (filter.round) {
Expand Down Expand Up @@ -603,6 +635,12 @@ export class ElasticIndexerHelper {
]));
}

if (filter.isScCall !== undefined) {
elasticQuery = filter.isScCall
? elasticQuery.withMustCondition(QueryType.Match('isScCall', true))
: elasticQuery.withMustNotCondition(QueryType.Match('isScCall', true));
}

return elasticQuery;
}

Expand Down
4 changes: 4 additions & 0 deletions src/common/indexer/entities/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,8 @@ export interface Transaction {
scResults: any[];
version: number;
relayerAddr: string;
relayer: string;
relayerSignature: string;
isRelayed: boolean;
isScCall: boolean;
}
24 changes: 23 additions & 1 deletion src/endpoints/accounts/account.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ export class AccountController {
@ApiQuery({ name: 'isSmartContract', description: 'Return total smart contracts count', required: false })
@ApiQuery({ name: 'name', description: 'Filter accounts by assets name', required: false })
@ApiQuery({ name: 'tags', description: 'Filter accounts by assets tags', required: false })
@ApiQuery({ name: 'search', description: 'Search by account address, assets name', required: false })
@ApiQuery({ name: 'excludeTags', description: 'Exclude specific tags from result', required: false })
@ApiQuery({ name: 'hasAssets', description: 'Returns a list of accounts that have assets', required: false })
async getAccountsCount(
Expand All @@ -156,6 +157,7 @@ export class AccountController {
@Query("tags", ParseArrayPipe) tags?: string[],
@Query("excludeTags", ParseArrayPipe) excludeTags?: string[],
@Query("hasAssets", ParseBoolPipe) hasAssets?: boolean,
@Query("search") search?: string,
): Promise<number> {
return await this.accountService.getAccountsCount(
new AccountQueryOptions(
Expand All @@ -166,6 +168,7 @@ export class AccountController {
tags,
excludeTags,
hasAssets,
search,
}));
}

Expand All @@ -178,6 +181,7 @@ export class AccountController {
@Query("tags", ParseArrayPipe) tags?: string[],
@Query("excludeTags", ParseArrayPipe) excludeTags?: string[],
@Query("hasAssets", ParseBoolPipe) hasAssets?: boolean,
@Query("search") search?: string,
): Promise<number> {
return await this.accountService.getAccountsCount(
new AccountQueryOptions(
Expand All @@ -188,6 +192,7 @@ export class AccountController {
tags,
excludeTags,
hasAssets,
search,
}));
}

Expand Down Expand Up @@ -877,6 +882,7 @@ export class AccountController {
@ApiQuery({ name: 'computeScamInfo', required: false, type: Boolean })
@ApiQuery({ name: 'senderOrReceiver', description: 'One address that current address interacted with', required: false })
@ApiQuery({ name: 'isRelayed', description: 'Returns isRelayed transactions details', required: false, type: Boolean })
@ApiQuery({ name: 'isScCall', description: 'Returns sc call 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 })
@ApiQuery({ name: 'withRelayedScresults', description: 'If set to true, will include smart contract results that resemble relayed transactions', required: false, type: Boolean })
async getAccountTransactions(
Expand Down Expand Up @@ -905,6 +911,7 @@ export class AccountController {
@Query('withBlockInfo', ParseBoolPipe) withBlockInfo?: boolean,
@Query('senderOrReceiver', ParseAddressPipe) senderOrReceiver?: string,
@Query('isRelayed', ParseBoolPipe) isRelayed?: boolean,
@Query('isScCall', ParseBoolPipe) isScCall?: boolean,
@Query('withActionTransferValue', ParseBoolPipe) withActionTransferValue?: boolean,
@Query('withRelayedScresults', ParseBoolPipe) withRelayedScresults?: boolean,
) {
Expand All @@ -925,6 +932,7 @@ export class AccountController {
order,
senderOrReceiver,
isRelayed,
isScCall,
round,
withRelayedScresults,
});
Expand All @@ -949,6 +957,7 @@ export class AccountController {
@ApiQuery({ name: 'round', description: 'Round number', required: false })
@ApiQuery({ name: 'senderOrReceiver', description: 'One address that current address interacted with', required: false })
@ApiQuery({ name: 'isRelayed', description: 'Returns isRelayed transactions details', required: false, type: Boolean })
@ApiQuery({ name: 'isScCall', description: 'Returns sc call transactions details', required: false, type: Boolean })
@ApiQuery({ name: 'withRelayedScresults', description: 'If set to true, will include smart contract results that resemble relayed transactions', required: false, type: Boolean })
async getAccountTransactionsCount(
@Param('address', ParseAddressPipe) address: string,
Expand All @@ -966,6 +975,7 @@ export class AccountController {
@Query('round', ParseIntPipe) round?: number,
@Query('senderOrReceiver', ParseAddressPipe) senderOrReceiver?: string,
@Query('isRelayed', ParseBoolPipe) isRelayed?: boolean,
@Query('isScCall', ParseBoolPipe) isScCall?: boolean,
@Query('withRelayedScresults', ParseBoolPipe) withRelayedScresults?: boolean,

): Promise<number> {
Expand All @@ -984,6 +994,7 @@ export class AccountController {
after,
senderOrReceiver,
isRelayed,
isScCall,
round,
withRelayedScresults,
}), address);
Expand All @@ -1010,6 +1021,7 @@ export class AccountController {
@ApiQuery({ name: 'round', description: 'Round number', required: false })
@ApiQuery({ name: 'fields', description: 'List of fields to filter by', required: false, isArray: true, style: 'form', explode: false })
@ApiQuery({ name: 'relayer', description: 'Address of the relayer', required: false })
@ApiQuery({ name: 'isScCall', description: 'Returns sc call transactions details', required: false, type: Boolean })
@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 })
Expand All @@ -1018,6 +1030,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,
Expand All @@ -1041,10 +1054,12 @@ export class AccountController {
@Query('withUsername', ParseBoolPipe) withUsername?: boolean,
@Query('withBlockInfo', ParseBoolPipe) withBlockInfo?: boolean,
@Query('senderOrReceiver', ParseAddressPipe) senderOrReceiver?: string,
@Query('isScCall', ParseBoolPipe) isScCall?: boolean,
@Query('withLogs', ParseBoolPipe) withLogs?: boolean,
@Query('withOperations', ParseBoolPipe) withOperations?: boolean,
@Query('withActionTransferValue', ParseBoolPipe) withActionTransferValue?: boolean,
@Query('withRefunds', ParseBoolPipe) withRefunds?: boolean,
@Query('withTxsRelayedByAddress', ParseBoolPipe) withTxsRelayedByAddress?: boolean,
): Promise<Transaction[]> {
const options = TransactionQueryOptions.applyDefaultOptions(
size, { withScamInfo, withUsername, withBlockInfo, withOperations, withLogs, withActionTransferValue });
Expand All @@ -1067,6 +1082,8 @@ export class AccountController {
relayer,
round,
withRefunds,
withTxsRelayedByAddress,
isScCall,
}),
new QueryPagination({ from, size }),
options,
Expand All @@ -1075,7 +1092,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 })
Expand All @@ -1089,6 +1106,7 @@ export class AccountController {
@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: 'isScCall', description: 'Returns sc call transactions details', required: false, type: Boolean })
@ApiQuery({ name: 'senderOrReceiver', description: 'One address that current address interacted with', required: false })
@ApiQuery({ name: 'withRefunds', description: 'Include refund transactions', required: false })
async getAccountTransfersCount(
Expand All @@ -1106,6 +1124,7 @@ export class AccountController {
@Query('after', ParseIntPipe) after?: number,
@Query('round', ParseIntPipe) round?: number,
@Query('senderOrReceiver', ParseAddressPipe) senderOrReceiver?: string,
@Query('isScCall', ParseBoolPipe) isScCall?: boolean,
@Query('withRefunds', ParseBoolPipe) withRefunds?: boolean,
): Promise<number> {
return await this.transferService.getTransfersCount(new TransactionFilter({
Expand All @@ -1123,6 +1142,7 @@ export class AccountController {
after,
senderOrReceiver,
round,
isScCall,
withRefunds,
}));
}
Expand All @@ -1145,6 +1165,7 @@ export class AccountController {
@Query('round', ParseIntPipe) round?: number,
@Query('senderOrReceiver', ParseAddressPipe) senderOrReceiver?: string,
@Query('withRefunds', ParseBoolPipe) withRefunds?: boolean,
@Query('isScCall', ParseBoolPipe) isScCall?: boolean,
): Promise<number> {
return await this.transferService.getTransfersCount(new TransactionFilter({
address,
Expand All @@ -1162,6 +1183,7 @@ export class AccountController {
senderOrReceiver,
round,
withRefunds,
isScCall,
}));
}

Expand Down
Loading

0 comments on commit 1d757c4

Please sign in to comment.