From 68c8386facee8d7f3a20cadd417a8dcc43ecbac9 Mon Sep 17 00:00:00 2001 From: Claudiu Lataretu Date: Tue, 5 Sep 2023 18:47:23 +0300 Subject: [PATCH 1/5] SERVICES-1824: add cached addresses with permissions - add caching for escrow SC keys - add method to get addresses with permissions Signed-off-by: Claudiu Lataretu --- .../escrow/services/escrow.abi.service.ts | 40 +++++++++++++++++++ .../escrow/services/escrow.setter.service.ts | 10 +++++ 2 files changed, 50 insertions(+) diff --git a/src/modules/escrow/services/escrow.abi.service.ts b/src/modules/escrow/services/escrow.abi.service.ts index 9b2a37738..d22bc7599 100644 --- a/src/modules/escrow/services/escrow.abi.service.ts +++ b/src/modules/escrow/services/escrow.abi.service.ts @@ -17,12 +17,16 @@ import { ErrorLoggerAsync } from 'src/helpers/decorators/error.logger'; import { GetOrSetCache } from 'src/helpers/decorators/caching.decorator'; import { oneDay } from 'src/helpers/helpers'; import { CacheTtlInfo } from 'src/services/caching/cache.ttl.info'; +import { CachingService } from 'src/services/caching/cache.service'; +import { EscrowSetterService } from './escrow.setter.service'; @Injectable() export class EscrowAbiService extends GenericAbiService { constructor( protected readonly mxProxy: MXProxyService, private readonly mxGateway: MXGatewayService, + private readonly cachingService: CachingService, + private readonly escrowSetter: EscrowSetterService, ) { super(mxProxy); } @@ -293,4 +297,40 @@ export class EscrowAbiService extends GenericAbiService { return []; } } + + @ErrorLoggerAsync({ + className: EscrowAbiService.name, + logArgs: true, + }) + @GetOrSetCache({ + baseKey: 'escrow', + remoteTtl: oneDay(), + }) + async allAddressesWithPermissions(): Promise { + return await this.getAllAddressesWithPermissionsRaw(); + } + + async getAllAddressesWithPermissionsRaw(): Promise { + let hexValues = await this.cachingService.getCache( + `escrow.scKeys`, + ); + if (!hexValues || hexValues === undefined) { + hexValues = await this.mxGateway.getSCStorageKeys( + scAddress.escrow, + [], + ); + await this.escrowSetter.setSCStorageKeys(hexValues); + } + + const addresses = []; + const permissionsHex = Buffer.from('permissions').toString('hex'); + Object.keys(hexValues).forEach((key) => { + if (key.includes(permissionsHex)) { + const addressHex = key.split(permissionsHex)[1]; + addresses.push(Address.fromHex(addressHex).bech32()); + } + }); + + return addresses; + } } diff --git a/src/modules/escrow/services/escrow.setter.service.ts b/src/modules/escrow/services/escrow.setter.service.ts index a6e81da11..8ba2971f0 100644 --- a/src/modules/escrow/services/escrow.setter.service.ts +++ b/src/modules/escrow/services/escrow.setter.service.ts @@ -5,6 +5,7 @@ import { CachingService } from 'src/services/caching/cache.service'; import { GenericSetterService } from 'src/services/generics/generic.setter.service'; import { Logger } from 'winston'; import { ScheduledTransferModel } from '../models/escrow.model'; +import { CacheTtlInfo } from 'src/services/caching/cache.ttl.info'; @Injectable() export class EscrowSetterService extends GenericSetterService { @@ -70,4 +71,13 @@ export class EscrowSetterService extends GenericSetterService { oneDay(), ); } + + async setSCStorageKeys(value: object): Promise { + return await this.setData( + this.getCacheKey('scKeys'), + value, + CacheTtlInfo.ContractState.remoteTtl, + CacheTtlInfo.ContractState.localTtl, + ); + } } From bdfec3d6d7a5c5f1b1fff6dcd469cb488b85eb07 Mon Sep 17 00:00:00 2001 From: Claudiu Lataretu Date: Tue, 5 Sep 2023 18:49:23 +0300 Subject: [PATCH 2/5] SERVICES-1824: improve escrow address permission query - use cached addresses with permissions to check if the address has any permission Signed-off-by: Claudiu Lataretu --- src/modules/escrow/services/escrow.abi.service.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/modules/escrow/services/escrow.abi.service.ts b/src/modules/escrow/services/escrow.abi.service.ts index d22bc7599..7c76cc9bc 100644 --- a/src/modules/escrow/services/escrow.abi.service.ts +++ b/src/modules/escrow/services/escrow.abi.service.ts @@ -270,6 +270,12 @@ export class EscrowAbiService extends GenericAbiService { remoteTtl: oneDay(), }) async addressPermission(address: string): Promise { + const addressesWithPermissions = + await this.allAddressesWithPermissions(); + if (!addressesWithPermissions.includes(address)) { + return [SCPermissions.NONE]; + } + return await this.getAddressPermissionRaw(address); } From 4101699ad5dbcf35bf2d06e12a01553197253170 Mon Sep 17 00:00:00 2001 From: Claudiu Lataretu Date: Tue, 5 Sep 2023 18:50:45 +0300 Subject: [PATCH 3/5] SERVICES-1824: improve escrow receivers query - use cached sc keys to get the escrow receivers for a sender Signed-off-by: Claudiu Lataretu --- src/modules/escrow/services/escrow.abi.service.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/modules/escrow/services/escrow.abi.service.ts b/src/modules/escrow/services/escrow.abi.service.ts index 7c76cc9bc..0887df837 100644 --- a/src/modules/escrow/services/escrow.abi.service.ts +++ b/src/modules/escrow/services/escrow.abi.service.ts @@ -114,10 +114,17 @@ export class EscrowAbiService extends GenericAbiService { } async getAllReceiversRaw(senderAddress: string): Promise { - const hexValues = await this.mxGateway.getSCStorageKeys( - scAddress.escrow, - [], + let hexValues = await this.cachingService.getCache( + `escrow.scKeys`, ); + if (!hexValues || hexValues === undefined) { + hexValues = await this.mxGateway.getSCStorageKeys( + scAddress.escrow, + [], + ); + await this.escrowSetter.setSCStorageKeys(hexValues); + } + const receivers = []; const allSendersHex = Buffer.from('allSenders').toString('hex'); const itemHex = Buffer.from('.item').toString('hex'); From 44b3fc093cdda2496ec1e8992764468b0330ea54 Mon Sep 17 00:00:00 2001 From: Claudiu Lataretu Date: Tue, 5 Sep 2023 18:51:33 +0300 Subject: [PATCH 4/5] SERVICES-1824: refresh cached escrow sc keys on events Signed-off-by: Claudiu Lataretu --- .../rabbitmq/handlers/escrow.handler.service.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/modules/rabbitmq/handlers/escrow.handler.service.ts b/src/modules/rabbitmq/handlers/escrow.handler.service.ts index 5d3b17bb8..74ce5ff28 100644 --- a/src/modules/rabbitmq/handlers/escrow.handler.service.ts +++ b/src/modules/rabbitmq/handlers/escrow.handler.service.ts @@ -6,8 +6,10 @@ import { } from '@multiversx/sdk-exchange'; import { Inject, Injectable } from '@nestjs/common'; import { RedisPubSub } from 'graphql-redis-subscriptions'; +import { scAddress } from 'src/config'; import { EscrowAbiService } from 'src/modules/escrow/services/escrow.abi.service'; import { EscrowSetterService } from 'src/modules/escrow/services/escrow.setter.service'; +import { MXGatewayService } from 'src/services/multiversx-communication/mx.gateway.service'; import { PUB_SUB } from 'src/services/redis.pubSub.module'; @Injectable() @@ -15,6 +17,7 @@ export class EscrowHandlerService { constructor( private readonly escrowAbi: EscrowAbiService, private readonly escrowSetter: EscrowSetterService, + private readonly mxGateway: MXGatewayService, @Inject(PUB_SUB) private pubSub: RedisPubSub, ) {} @@ -82,6 +85,13 @@ export class EscrowHandlerService { sender: string, receiver: string, ): Promise { + const scKeys = await this.mxGateway.getSCStorageKeys( + scAddress.escrow, + [], + ); + const cachedKey = await this.escrowSetter.setSCStorageKeys(scKeys); + await this.deleteCacheKeys([cachedKey]); + const [allSenders, allReceivers, scheduledTransfers] = await Promise.all([ this.escrowAbi.getAllSendersRaw(receiver), From 514bbcef3f6d70aa5598e8903ad9585e91acc21a Mon Sep 17 00:00:00 2001 From: Claudiu Lataretu Date: Tue, 5 Sep 2023 19:07:02 +0300 Subject: [PATCH 5/5] SERVICES-1824: fix escrow abi service unit tests Signed-off-by: Claudiu Lataretu --- src/modules/escrow/specs/escrow.abi.service.spec.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/modules/escrow/specs/escrow.abi.service.spec.ts b/src/modules/escrow/specs/escrow.abi.service.spec.ts index da08b0453..8ad0145c4 100644 --- a/src/modules/escrow/specs/escrow.abi.service.spec.ts +++ b/src/modules/escrow/specs/escrow.abi.service.spec.ts @@ -11,10 +11,12 @@ import { CacheModule } from '@nestjs/cache-manager'; import { CachingService } from 'src/services/caching/cache.service'; import { ApiConfigService } from 'src/helpers/api.config.service'; import winston from 'winston'; +import { EscrowSetterService } from '../services/escrow.setter.service'; describe('EscrowAbiService', () => { let service: EscrowAbiService; let mxGateway: MXGatewayService; + let cachingService: CachingService; beforeAll(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -27,6 +29,7 @@ describe('EscrowAbiService', () => { ], providers: [ EscrowAbiService, + EscrowSetterService, MXProxyServiceProvider, MXGatewayServiceProvider, CachingService, @@ -36,6 +39,7 @@ describe('EscrowAbiService', () => { service = module.get(EscrowAbiService); mxGateway = module.get(MXGatewayService); + cachingService = module.get(CachingService); }); it('should be defined', () => { @@ -119,6 +123,7 @@ describe('EscrowAbiService', () => { receivers = await service.getAllReceiversRaw(sender.bech32()); expect(receivers).toEqual([]); + await cachingService.deleteInCache(`escrow.scKeys`); }); it('should get one receiver for sender', async () => { @@ -136,6 +141,7 @@ describe('EscrowAbiService', () => { expect(receivers).toEqual([ 'erd1devnet6uy8xjusvusfy3q83qadfhwrtty5fwa8ceh9cl60q2p6ysra7aaa', ]); + await cachingService.deleteInCache(`escrow.scKeys`); }); it('should get two receivers for sender', async () => { @@ -160,5 +166,6 @@ describe('EscrowAbiService', () => { 'erd1devnet6uy8xjusvusfy3q83qadfhwrtty5fwa8ceh9cl60q2p6ysra7aaa', 'erd1932eft30w753xyvme8d49qejgkjc09n5e49w4mwdjtm0neld797su0dlxp', ]); + await cachingService.deleteInCache(`escrow.scKeys`); }); });