diff --git a/src/modules/analytics/models/trading.activity.model.ts b/src/modules/analytics/models/trading.activity.model.ts index 0112bf702..df8092197 100644 --- a/src/modules/analytics/models/trading.activity.model.ts +++ b/src/modules/analytics/models/trading.activity.model.ts @@ -1,5 +1,5 @@ import { Field, ObjectType, registerEnumType } from '@nestjs/graphql'; -import { EsdtTokenPaymentModel } from 'src/modules/tokens/models/esdt.token.payment.model'; +import { EsdtToken } from 'src/modules/tokens/models/esdtToken.model'; export enum TradingActivityAction { 'BUY' = 'BUY', @@ -17,9 +17,9 @@ export class TradingActivityModel { @Field() action: TradingActivityAction; @Field() - inputToken: EsdtTokenPaymentModel; + inputToken: EsdtToken; @Field() - outputToken: EsdtTokenPaymentModel; + outputToken: EsdtToken; constructor(init?: Partial) { Object.assign(this, init); diff --git a/src/modules/analytics/services/analytics.compute.service.ts b/src/modules/analytics/services/analytics.compute.service.ts index 0f1170db7..9f7f32be1 100644 --- a/src/modules/analytics/services/analytics.compute.service.ts +++ b/src/modules/analytics/services/analytics.compute.service.ts @@ -28,8 +28,7 @@ import { import { SwapEvent } from '@multiversx/sdk-exchange'; import { convertEventTopicsAndDataToBase64 } from 'src/utils/elastic.search.utils'; import { ElasticSearchEventsService } from 'src/services/elastic-search/services/es.events.service'; -import { RawElasticEventType } from 'src/services/elastic-search/entities/raw.elastic.event'; -import { EsdtTokenPaymentModel } from 'src/modules/tokens/models/esdt.token.payment.model'; +import { PairMetadata } from 'src/modules/router/models/pair.metadata.model'; @Injectable() export class AnalyticsComputeService { @@ -304,11 +303,11 @@ export class AnalyticsComputeService { return await this.computeTokenTradingActivity(tokenID); } - async determineBaseAndQuoteTokens( + private determineBaseAndQuoteTokens( pairAddress: string, - ): Promise<{ baseToken: string; quoteToken: string }> { - const pairsMetadata = await this.routerAbi.pairsMetadata(); - const commonTokens = await this.routerAbi.commonTokensForUserPairs(); + pairsMetadata: PairMetadata[], + commonTokens: string[], + ): { baseToken: string; quoteToken: string } { const sortedCommonTokens = commonTokens.sort((a, b) => { const order = ['USD', 'EGLD']; const indexA = order.findIndex((token) => a.includes(token)); @@ -346,37 +345,49 @@ export class AnalyticsComputeService { const events = await this.elasticEventsService.getPairTradingEvents( pairAddress, ); + const pairsMetadata = await this.routerAbi.pairsMetadata(); + const commonTokens = await this.routerAbi.commonTokensForUserPairs(); - const { quoteToken } = await this.determineBaseAndQuoteTokens( + const { quoteToken, baseToken } = this.determineBaseAndQuoteTokens( pairAddress, + pairsMetadata, + commonTokens, ); + const tokens = await this.tokenService.getAllTokensMetadata([ + quoteToken, + baseToken, + ]); + for (const event of events) { const eventConverted = convertEventTopicsAndDataToBase64(event); - const swapEvent = new SwapEvent(eventConverted); + const swapEvent = new SwapEvent(eventConverted).toJSON(); - const tokenIn = swapEvent.getTokenIn(); - const tokenOut = swapEvent.getTokenOut(); + const tokenIn = swapEvent.tokenIn; + const tokenOut = swapEvent.tokenOut; const action = quoteToken === tokenOut.tokenID ? TradingActivityAction.BUY : TradingActivityAction.SELL; - results.push({ - hash: event.txHash, - inputToken: { - tokenIdentifier: tokenIn.tokenID, - amount: new BigNumber(tokenIn.amount).toFixed(), - tokenNonce: new BigNumber(tokenIn.nonce).toNumber(), - }, - outputToken: { - tokenIdentifier: tokenOut.tokenID, - amount: new BigNumber(tokenOut.amount).toFixed(), - tokenNonce: new BigNumber(tokenOut.nonce).toNumber(), - }, - timestamp: String(event.timestamp), - action, - }); + const inputToken = tokens.find( + (token) => token.identifier === tokenIn.tokenID, + ); + inputToken.balance = tokenIn.amount; + const outputToken = tokens.find( + (token) => token.identifier === tokenOut.tokenID, + ); + outputToken.balance = tokenOut.amount; + + results.push( + new TradingActivityModel({ + hash: event.txHash, + inputToken: { ...inputToken }, + outputToken: { ...outputToken }, + timestamp: String(event.timestamp), + action, + }), + ); } return results; @@ -385,8 +396,9 @@ export class AnalyticsComputeService { async computeTokenTradingActivity( tokenID: string, ): Promise { - let filteredEvents: RawElasticEventType[] = []; const pairsMetadata = await this.routerAbi.pairsMetadata(); + const commonTokens = await this.routerAbi.commonTokensForUserPairs(); + const pairsTokens = new Set(); const pairsAddresses = pairsMetadata .filter( @@ -396,14 +408,28 @@ export class AnalyticsComputeService { ) .map((pair) => pair.address); - filteredEvents = await this.elasticEventsService.getTokenTradingEvents( - tokenID, - pairsAddresses, - 10, - ); + let filteredEvents = + await this.elasticEventsService.getTokenTradingEvents( + tokenID, + pairsAddresses, + 10, + ); filteredEvents = filteredEvents.slice(0, 10); + const matchedPairs = pairsMetadata.filter((pair) => + filteredEvents.some((event) => event.address === pair.address), + ); + + matchedPairs.forEach((pair) => { + pairsTokens.add(pair.firstTokenID); + pairsTokens.add(pair.secondTokenID); + }); + + const tokens = await this.tokenService.getAllTokensMetadata( + Array.from(pairsTokens), + ); + return filteredEvents.map((event) => { const eventConverted = convertEventTopicsAndDataToBase64(event); const swapEvent = new SwapEvent(eventConverted).toJSON(); @@ -411,26 +437,34 @@ export class AnalyticsComputeService { const tokenIn = swapEvent.tokenIn; const tokenOut = swapEvent.tokenOut; + const inputToken = tokens.find( + (token) => token.identifier === tokenIn.tokenID, + ); + + inputToken.balance = tokenIn.amount; + const outputToken = tokens.find( + (token) => token.identifier === tokenOut.tokenID, + ); + outputToken.balance = tokenOut.amount; + + const { quoteToken } = this.determineBaseAndQuoteTokens( + swapEvent.address, + pairsMetadata, + commonTokens, + ); + const action = - tokenID === tokenOut.tokenID + quoteToken === tokenOut.tokenID ? TradingActivityAction.BUY : TradingActivityAction.SELL; - return { + return new TradingActivityModel({ hash: event.txHash, - inputToken: new EsdtTokenPaymentModel({ - tokenIdentifier: tokenIn.tokenID, - tokenNonce: tokenIn.nonce, - amount: tokenIn.amount, - }), - outputToken: new EsdtTokenPaymentModel({ - tokenIdentifier: tokenOut.tokenID, - tokenNonce: tokenOut.nonce, - amount: tokenOut.amount, - }), + inputToken: { ...inputToken }, + outputToken: { ...outputToken }, timestamp: String(event.timestamp), action, - }; + }); }); } } diff --git a/src/services/crons/analytics.cache.warmer.service.ts b/src/services/crons/analytics.cache.warmer.service.ts index e6fd90c15..84c30b0a7 100644 --- a/src/services/crons/analytics.cache.warmer.service.ts +++ b/src/services/crons/analytics.cache.warmer.service.ts @@ -61,7 +61,7 @@ export class AnalyticsCacheWarmerService { tradingActivity, ); - cachedKeys.push(...pairCachedKeys); + cachedKeys.push(pairCachedKeys); tokenIDs.add(pair.firstTokenID); tokenIDs.add(pair.secondTokenID); @@ -78,7 +78,7 @@ export class AnalyticsCacheWarmerService { tradingActivity, ); - cachedKeys.push(...tokenCachedKeys); + cachedKeys.push(tokenCachedKeys); } await this.deleteCacheKeys(cachedKeys);