Skip to content

preocompute account details #1475

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 63 commits into
base: feat/performance-improvements
Choose a base branch
from
Draft
Changes from 1 commit
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
1ed33e8
create redirect to media controller
gabrielmatei Nov 18, 2024
dbdd216
redirect to media
gabrielmatei Nov 22, 2024
898b933
add unit tests
gabrielmatei Mar 11, 2025
2649ec9
Merge remote-tracking branch 'origin/development' into API-73-media-u…
gabrielmatei Mar 11, 2025
26afc3e
fixes
gabrielmatei Mar 11, 2025
b91e355
create NFT_THUMBNAIL_DEFAULT based on configs
gabrielmatei Mar 11, 2025
b5c8eb0
update media storage urls
gabrielmatei Mar 11, 2025
1a46b7d
apply redirect media on cached media
gabrielmatei Mar 12, 2025
046bbbb
priority ppu metadata first implementation
dragos-rebegea Mar 13, 2025
522d28a
fix distributeTransactionsIntoGasBuckets
dragos-rebegea Mar 13, 2025
6bed793
add last bucket only it has transactions
dragos-rebegea Mar 13, 2025
3116d1d
fix shard validation
dragos-rebegea Mar 13, 2025
2ad1561
fixes
gabrielmatei Mar 14, 2025
97b8b84
add csp header
gabrielmatei Mar 14, 2025
1f74198
update header
gabrielmatei Mar 14, 2025
27fcb43
stream files
gabrielmatei Mar 14, 2025
c4b42e2
update headers
gabrielmatei Mar 17, 2025
4a24c77
fix log message
gabrielmatei Mar 18, 2025
371b407
Merge branch 'API-73-media-url-resolving' into API-499-compute-media-…
gabrielmatei Mar 18, 2025
8a9e42e
Merge pull request #1460 from multiversx/API-73-media-url-resolving
gabrielmatei Mar 18, 2025
8957dc8
Merge pull request #1461 from multiversx/API-499-compute-media-url-links
gabrielmatei Mar 18, 2025
cc9f50f
fix lint errors on media.controller.ts
gabrielmatei Mar 18, 2025
eee5073
fix tests
gabrielmatei Mar 18, 2025
bda6634
refactor + add test ppu
cfaur09 Mar 18, 2025
ab0cc03
Merge pull request #1467 from multiversx/fix-media-tests
gabrielmatei Mar 18, 2025
0129970
linter fixes
cfaur09 Mar 18, 2025
bb2f30d
fix unit tests
cfaur09 Mar 18, 2025
793fb17
fix test
cfaur09 Mar 18, 2025
b4f9aa9
remove async await for sync functions
GuticaStefan Mar 19, 2025
8c0ff46
Merge pull request #1466 from multiversx/feat/media-redirect
dragos-rebegea Mar 20, 2025
958d9d0
remove async await for sync functions (#1469)
GuticaStefan Mar 24, 2025
fb35d87
add epoch field for transactions (#1464)
bogdan-rosianu Mar 24, 2025
232fd06
added missing relayer fields for sending txs (#1472)
bogdan-rosianu Mar 25, 2025
cc95a6a
Update dependencies and refactor imports for transaction processing
cfaur09 Mar 26, 2025
1466d6f
update tests
cfaur09 Mar 26, 2025
de00ac6
update API to latest nestjs-sdk
cfaur09 Mar 26, 2025
f48219c
add empty line after import
cfaur09 Mar 27, 2025
b7bc85c
precompute account details
GuticaStefan Mar 31, 2025
17f8863
add support for identities secondary sort criteria
cfaur09 Mar 31, 2025
d49bd36
use mongoose instead of typeorm
GuticaStefan Mar 31, 2025
8ccec33
Media redirect bugfixing (#1471)
gabrielmatei Mar 31, 2025
eec5e94
add andromeda support (#1468)
bogdan-rosianu Mar 31, 2025
ffe0ed5
precompute account tokens/nfts
GuticaStefan Mar 31, 2025
a8efeb2
db queries improvements
GuticaStefan Apr 1, 2025
35f3554
fix token isPaused property (#1477)
cfaur09 Apr 2, 2025
c523366
fetch token/nft for address from db
GuticaStefan Apr 2, 2025
cec74b2
add support for refreshRate round length (#1478)
cfaur09 Apr 3, 2025
008eaf0
Merge pull request #1473 from multiversx/API-530-update-api-multivers…
dragos-rebegea Apr 3, 2025
5f954f2
Merge branch 'development' into API-538-add-support-for-identities-se…
cfaur09 Apr 3, 2025
d342aa0
add support for receivedAt timestamp for account nfts (#1462)
cfaur09 Apr 3, 2025
ebfbe05
fix naming
dragos-rebegea Apr 3, 2025
e649765
lowercase naming
dragos-rebegea Apr 3, 2025
2de799a
Merge pull request #1463 from multiversx/transactions-ppu-by-shard
dragos-rebegea Apr 3, 2025
977dd05
improve sorting with multiple criterias (#1479)
dragos-rebegea Apr 3, 2025
a383889
Merge pull request #1476 from multiversx/API-538-add-support-for-iden…
dragos-rebegea Apr 3, 2025
29ee4b9
no cache on v2 endpoints
GuticaStefan Apr 7, 2025
622024b
Merge branch 'development' into API-507-api-improvements
GuticaStefan Apr 7, 2025
8b36bf3
restore tx processor
GuticaStefan Apr 7, 2025
a00fe8c
populate db script
GuticaStefan Apr 7, 2025
c34fa45
update scripts
gabrielmatei Apr 7, 2025
bef97d0
add index on populate db script
GuticaStefan Apr 8, 2025
ef67998
ignore account code in query
gabrielmatei Apr 8, 2025
1173804
remove no cache decorator
GuticaStefan Apr 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
restore tx processor
  • Loading branch information
GuticaStefan committed Apr 7, 2025
commit 8b36bf3dae5b760a74479003fa07472f0cc31f82
343 changes: 168 additions & 175 deletions src/crons/transaction.processor/transaction.processor.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,36 +11,29 @@ import { TransferOwnershipExtractor } from "./extractor/transfer.ownership.extra
import { MetricsEvents } from "src/utils/metrics-events.constants";
import { LogMetricsEvent } from "src/common/entities/log.metrics.event";
import { CacheService } from "@multiversx/sdk-nestjs-cache";
import { AddressUtils, BinaryUtils, OriginLogger } from "@multiversx/sdk-nestjs-common";
import { BinaryUtils, OriginLogger } from "@multiversx/sdk-nestjs-common";
import { PerformanceProfiler } from "@multiversx/sdk-nestjs-monitoring";
import { StakeFunction } from "src/endpoints/transactions/transaction-action/recognizers/staking/entities/stake.function";
import { AccountService } from "src/endpoints/accounts/account.service";
import { AccountDetails, AccountDetailsRepository } from "src/common/indexer/db/src";
import { TokenService } from "src/endpoints/tokens/token.service";
import { QueryPagination } from "src/common/entities/query.pagination";
import { TokenFilter } from "src/endpoints/tokens/entities/token.filter";
import { NftService } from "src/endpoints/nfts/nft.service";
import { NftFilter } from "src/endpoints/nfts/entities/nft.filter";
import { ShardTransaction, TransactionProcessor } from "@multiversx/sdk-transaction-processor";

@Injectable()
export class TransactionProcessorService {
private readonly systemAddresses = [
"erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqllls0lczs7",
"erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqplllst77y4l",
"erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u",
"erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqrlllsrujgla",
"erd1qqqqqqqqqqqqqqqpqqqqqqqqqrlllllllllllllllllllllllllsn60f0k",
"erd1qqqqqqqqqqqqqqqpqqqqqqqqlllllllllllllllllllllllllllsr9gav8",
"erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqylllslmq6y6",
"erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0llllsqkarq6",
"erd1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6gq4hu",
"erd17rc0pu8s7rc0pu8s7rc0pu8s7rc0pu8s7rc0pu8s7rc0pu8s7rcqqkhty3",
"erd1lllllllllllllllllllllllllllllllllllllllllllllllllllsckry7t",
"erd1llllllllllllllllllllllllllllllllllllllllllllllllluqq2m3f0f",
"erd1llllllllllllllllllllllllllllllllllllllllllllllllluqsl6e366",
"erd1lllllllllllllllllllllllllllllllllllllllllllllllllupq9x7ny0"
];
// private readonly systemAddresses = [
// "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqllls0lczs7",
// "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqplllst77y4l",
// "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u",
// "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqrlllsrujgla",
// "erd1qqqqqqqqqqqqqqqpqqqqqqqqqrlllllllllllllllllllllllllsn60f0k",
// "erd1qqqqqqqqqqqqqqqpqqqqqqqqlllllllllllllllllllllllllllsr9gav8",
// "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqylllslmq6y6",
// "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0llllsqkarq6",
// "erd1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6gq4hu",
// "erd17rc0pu8s7rc0pu8s7rc0pu8s7rc0pu8s7rc0pu8s7rc0pu8s7rcqqkhty3",
// "erd1lllllllllllllllllllllllllllllllllllllllllllllllllllsckry7t",
// "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqq2m3f0f",
// "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqsl6e366",
// "erd1lllllllllllllllllllllllllllllllllllllllllllllllllupq9x7ny0"
// ];
private readonly logger = new OriginLogger(TransactionProcessorService.name);
private transactionProcessor: TransactionProcessor = new TransactionProcessor();

Expand All @@ -51,170 +44,81 @@ export class TransactionProcessorService {
@Inject('PUBSUB_SERVICE') private clientProxy: ClientProxy,
private readonly nodeService: NodeService,
private readonly eventEmitter: EventEmitter2,
private readonly accountDetailsRepository: AccountDetailsRepository,
private readonly accountService: AccountService,
private readonly tokenService: TokenService,
private readonly nftService: NftService,
// private readonly accountDetailsRepository: AccountDetailsRepository,
// private readonly accountService: AccountService,
// private readonly tokenService: TokenService,
// private readonly nftService: NftService,
) { }

@Cron('*/1 * * * * *')
async handleTx() {
await this.transactionProcessor.start({
gatewayUrl: this.apiConfigService.getGatewayUrl(),
maxLookBehind: this.apiConfigService.getTransactionProcessorMaxLookBehind(),
onTransactionsReceived: async (shard, nonce, transactions) => {
const profiler = new PerformanceProfiler('Processing new transactions');

const uniqueAddresses = new Set<string>();
this.logger.log(`New transactions: ${transactions.length} for shard ${shard} and nonce ${nonce}`);
const filteredTransactions = transactions.filter(transaction => transaction.status === 'success');
// Group transactions by address to determine which fields need updating
const addressUpdates = new Map<string, Set<string>>();

for (const transaction of filteredTransactions) {
// Only add addresses that are not system addresses
if (!this.systemAddresses.includes(transaction.sender)) {
uniqueAddresses.add(transaction.sender);
}
if (!this.systemAddresses.includes(transaction.receiver)) {
uniqueAddresses.add(transaction.receiver);
}

// Get fields to update for sender and receiver separately
const senderFields = this.getFieldsToUpdate(transaction);
const receiverFields = this.getFieldsToUpdate(transaction);

// Add fields to update for sender
if (!addressUpdates.has(transaction.sender)) {
addressUpdates.set(transaction.sender, new Set());
}
senderFields.forEach(field => addressUpdates.get(transaction.sender)?.add(field));

// Add fields to update for receiver
if (!addressUpdates.has(transaction.receiver)) {
addressUpdates.set(transaction.receiver, new Set());
}
receiverFields.forEach(field => addressUpdates.get(transaction.receiver)?.add(field));
}

for (const address of uniqueAddresses) {
const documentExists = await this.accountDetailsRepository.getAccount(address)
const fieldsToUpdate = documentExists ? (addressUpdates.get(address) ?? new Set())
: new Set(['guardianInfo', 'txCount', 'scrCount', 'timestamp', 'assets']);

// Only fetch account if we need to update fields
if (fieldsToUpdate.size > 0) {
const accountFetchOptions = {
withGuardianInfo: fieldsToUpdate.has('guardianInfo'),
withTxCount: fieldsToUpdate.has('txCount'),
withScrCount: fieldsToUpdate.has('scrCount'),
withTimestamp: fieldsToUpdate.has('timestamp'),
withAssets: fieldsToUpdate.has('assets')
}
// console.log('accountFetchOptions ', accountFetchOptions);
const accountDetails = await this.accountService.getAccount(address, accountFetchOptions) as AccountDetails;
if (fieldsToUpdate.has('tokens') || !documentExists) {
accountDetails.tokens = await this.tokenService.getTokensForAddress(address, new QueryPagination({ from: 0, size: 100 }), new TokenFilter());
}

if (fieldsToUpdate.has('nfts') || !documentExists) {
accountDetails.nfts = await this.nftService.getNftsForAddress(address, new QueryPagination({ from: 0, size: 100 }), new NftFilter());
}
// console.log('accountDetailed ', accountDetailed);
if (accountDetails) {
await this.accountDetailsRepository.updateAccount(accountDetails);
}
}
}
profiler.stop();
},
getLastProcessedNonce: async (shardId) => {
return await this.cachingService.get<number>(CacheInfo.TransactionProcessorShardNonce(shardId).key);
},
setLastProcessedNonce: async (shardId, nonce) => {
const event = new LogMetricsEvent();
event.args = [shardId, nonce];
this.eventEmitter.emit(
MetricsEvents.SetLastProcessedNonce,
event
);

await this.cachingService.set<number>(CacheInfo.TransactionProcessorShardNonce(shardId).key, nonce, CacheInfo.TransactionProcessorShardNonce(shardId).ttl);
},
});
}

private getFieldsToUpdate(transaction: ShardTransaction): Set<string> {
const fields = new Set<string>();

// Always update timestamp as it's transaction-related
fields.add('timestamp');

// Balance changes
if (transaction.value !== '0') {
fields.add('balance');
}

// Transaction count changes
fields.add('txCount');

// Smart contract interactions - only for smart contract addresses
if (AddressUtils.isSmartContractAddress(transaction.receiver)) {
fields.add('scrCount');
}

// Guardian changes - only for non-smart contract addresses
if (transaction.getDataFunctionName() === 'GuardAccount' || transaction.getDataFunctionName() === 'UnGuardAccount') {
fields.add('guardianInfo');
}

// Asset changes - check for transfer/mint/burn in a case-insensitive way
const functionName = transaction.getDataFunctionName()?.toLowerCase() ?? '';
if (functionName.includes('transfer') ||
functionName.includes('mint') ||
functionName.includes('burn')) {
fields.add('tokens');
fields.add('nfts');
}

return fields;
}

// @Cron('*/1 * * * * *')
// async handleNewTransactions() {
// async handleTx() {
// await this.transactionProcessor.start({
// gatewayUrl: this.apiConfigService.getGatewayUrl(),
// maxLookBehind: this.apiConfigService.getTransactionProcessorMaxLookBehind(),
// onTransactionsReceived: async (shard, nonce, transactions) => {
// const profiler = new PerformanceProfiler('Processing new transactions');

// const uniqueAddresses = new Set<string>();
// this.logger.log(`New transactions: ${transactions.length} for shard ${shard} and nonce ${nonce}`);

// const allInvalidatedKeys = [];

// for (const transaction of transactions) {
// const invalidatedTokenProperties = await this.tryInvalidateTokenProperties(transaction);
// const invalidatedOwnerKeys = await this.tryInvalidateOwner(transaction);
// const invalidatedCollectionPropertiesKeys = await this.tryInvalidateCollectionProperties(transaction);
// const invalidatedStakeTopUpKey = await this.tryInvalidateStakeTopup(transaction);

// allInvalidatedKeys.push(
// ...invalidatedTokenProperties,
// ...invalidatedOwnerKeys,
// ...invalidatedCollectionPropertiesKeys,
// ...invalidatedStakeTopUpKey,
// );
// const filteredTransactions = transactions.filter(transaction => transaction.status === 'success');
// // Group transactions by address to determine which fields need updating
// const addressUpdates = new Map<string, Set<string>>();

// for (const transaction of filteredTransactions) {
// // Only add addresses that are not system addresses
// if (!this.systemAddresses.includes(transaction.sender)) {
// uniqueAddresses.add(transaction.sender);
// }
// if (!this.systemAddresses.includes(transaction.receiver)) {
// uniqueAddresses.add(transaction.receiver);
// }

// // Get fields to update for sender and receiver separately
// const senderFields = this.getFieldsToUpdate(transaction);
// const receiverFields = this.getFieldsToUpdate(transaction);

// // Add fields to update for sender
// if (!addressUpdates.has(transaction.sender)) {
// addressUpdates.set(transaction.sender, new Set());
// }
// senderFields.forEach(field => addressUpdates.get(transaction.sender)?.add(field));

// // Add fields to update for receiver
// if (!addressUpdates.has(transaction.receiver)) {
// addressUpdates.set(transaction.receiver, new Set());
// }
// receiverFields.forEach(field => addressUpdates.get(transaction.receiver)?.add(field));
// }

// const uniqueInvalidatedKeys = allInvalidatedKeys.distinct();
// if (uniqueInvalidatedKeys.length > 0) {
// this.clientProxy.emit('deleteCacheKeys', uniqueInvalidatedKeys);
// for (const address of uniqueAddresses) {
// const documentExists = await this.accountDetailsRepository.getAccount(address)
// const fieldsToUpdate = documentExists ? (addressUpdates.get(address) ?? new Set())
// : new Set(['guardianInfo', 'txCount', 'scrCount', 'timestamp', 'assets']);

// // Only fetch account if we need to update fields
// if (fieldsToUpdate.size > 0) {
// const accountFetchOptions = {
// withGuardianInfo: fieldsToUpdate.has('guardianInfo'),
// withTxCount: fieldsToUpdate.has('txCount'),
// withScrCount: fieldsToUpdate.has('scrCount'),
// withTimestamp: fieldsToUpdate.has('timestamp'),
// withAssets: fieldsToUpdate.has('assets')
// }
// // console.log('accountFetchOptions ', accountFetchOptions);
// const accountDetails = await this.accountService.getAccount(address, accountFetchOptions) as AccountDetails;
// if (fieldsToUpdate.has('tokens') || !documentExists) {
// accountDetails.tokens = await this.tokenService.getTokensForAddress(address, new QueryPagination({ from: 0, size: 100 }), new TokenFilter());
// }

// if (fieldsToUpdate.has('nfts') || !documentExists) {
// accountDetails.nfts = await this.nftService.getNftsForAddress(address, new QueryPagination({ from: 0, size: 100 }), new NftFilter());
// }
// // console.log('accountDetailed ', accountDetailed);
// if (accountDetails) {
// await this.accountDetailsRepository.updateAccount(accountDetails);
// }
// }
// }

// const distinctSendersAndReceivers = transactions.selectMany(transaction => [transaction.sender, transaction.receiver]).distinct();
// const txCountInvalidationKeys = distinctSendersAndReceivers.map(address => CacheInfo.TxCount(address).key);
// await this.cachingService.batchDelCache(txCountInvalidationKeys);

// profiler.stop();
// },
// getLastProcessedNonce: async (shardId) => {
Expand All @@ -233,6 +137,95 @@ export class TransactionProcessorService {
// });
// }

// private getFieldsToUpdate(transaction: ShardTransaction): Set<string> {
// const fields = new Set<string>();

// // Always update timestamp as it's transaction-related
// fields.add('timestamp');

// // Balance changes
// if (transaction.value !== '0') {
// fields.add('balance');
// }

// // Transaction count changes
// fields.add('txCount');

// // Smart contract interactions - only for smart contract addresses
// if (AddressUtils.isSmartContractAddress(transaction.receiver)) {
// fields.add('scrCount');
// }

// // Guardian changes - only for non-smart contract addresses
// if (transaction.getDataFunctionName() === 'GuardAccount' || transaction.getDataFunctionName() === 'UnGuardAccount') {
// fields.add('guardianInfo');
// }

// // Asset changes - check for transfer/mint/burn in a case-insensitive way
// const functionName = transaction.getDataFunctionName()?.toLowerCase() ?? '';
// if (functionName.includes('transfer') ||
// functionName.includes('mint') ||
// functionName.includes('burn')) {
// fields.add('tokens');
// fields.add('nfts');
// }

// return fields;
// }

@Cron('*/1 * * * * *')
async handleNewTransactions() {
await this.transactionProcessor.start({
gatewayUrl: this.apiConfigService.getGatewayUrl(),
maxLookBehind: this.apiConfigService.getTransactionProcessorMaxLookBehind(),
onTransactionsReceived: async (shard, nonce, transactions) => {
const profiler = new PerformanceProfiler('Processing new transactions');

this.logger.log(`New transactions: ${transactions.length} for shard ${shard} and nonce ${nonce}`);

const allInvalidatedKeys = [];

for (const transaction of transactions) {
const invalidatedTokenProperties = await this.tryInvalidateTokenProperties(transaction);
const invalidatedOwnerKeys = await this.tryInvalidateOwner(transaction);
const invalidatedCollectionPropertiesKeys = await this.tryInvalidateCollectionProperties(transaction);
const invalidatedStakeTopUpKey = await this.tryInvalidateStakeTopup(transaction);

allInvalidatedKeys.push(
...invalidatedTokenProperties,
...invalidatedOwnerKeys,
...invalidatedCollectionPropertiesKeys,
...invalidatedStakeTopUpKey,
);
}

const uniqueInvalidatedKeys = allInvalidatedKeys.distinct();
if (uniqueInvalidatedKeys.length > 0) {
this.clientProxy.emit('deleteCacheKeys', uniqueInvalidatedKeys);
}

const distinctSendersAndReceivers = transactions.selectMany(transaction => [transaction.sender, transaction.receiver]).distinct();
const txCountInvalidationKeys = distinctSendersAndReceivers.map(address => CacheInfo.TxCount(address).key);
await this.cachingService.batchDelCache(txCountInvalidationKeys);

profiler.stop();
},
getLastProcessedNonce: async (shardId) => {
return await this.cachingService.get<number>(CacheInfo.TransactionProcessorShardNonce(shardId).key);
},
setLastProcessedNonce: async (shardId, nonce) => {
const event = new LogMetricsEvent();
event.args = [shardId, nonce];
this.eventEmitter.emit(
MetricsEvents.SetLastProcessedNonce,
event
);

await this.cachingService.set<number>(CacheInfo.TransactionProcessorShardNonce(shardId).key, nonce, CacheInfo.TransactionProcessorShardNonce(shardId).ttl);
},
});
}

//@ts-ignore
private async tryInvalidateTokenProperties(transaction: ShardTransaction): Promise<string[]> {
if (transaction.receiver !== this.apiConfigService.getEsdtContractAddress()) {
Expand Down