From 57ac4e3bf22cc237d3a1207c42de275399848d80 Mon Sep 17 00:00:00 2001 From: danielailie Date: Wed, 15 Nov 2023 15:44:29 +0200 Subject: [PATCH 01/11] Add proxy deployer --- package-lock.json | 51 +++++- package.json | 2 +- schema.gql | 10 +- src/abis/proxy-deployer.abi.json | 150 ++++++++++++++++++ src/app.module.ts | 2 + src/modules/auctions/contractLoader.ts | 2 + src/modules/auctions/marketplaceUtils.ts | 1 + .../proxy-deployer/models/AddMinterArgs.ts | 14 ++ .../proxy-deployer/models/DeployMinterArgs.ts | 28 ++++ .../proxy-deployer/models/Minter.dto.ts | 24 +++ .../proxy-deployer/models/MinterFilters.ts | 18 +++ .../proxy-deployer/models/MintersResponse.ts | 6 + src/modules/proxy-deployer/models/index.ts | 2 + .../models/requests/DeployMinterRequest.ts | 34 ++++ .../models/requests/whitelistMinterRequest.ts | 16 ++ .../proxy-deployer-caching.service.ts | 18 +++ .../proxy-deployer-mutations.resolver.ts | 37 +++++ .../proxy-deployer.abi.service.ts | 79 +++++++++ .../proxy-deployer/proxy-deployer.module.ts | 17 ++ .../proxy-deployer/proxy-deployer.service.ts | 81 ++++++++++ 20 files changed, 586 insertions(+), 6 deletions(-) create mode 100644 src/abis/proxy-deployer.abi.json create mode 100644 src/modules/proxy-deployer/models/AddMinterArgs.ts create mode 100644 src/modules/proxy-deployer/models/DeployMinterArgs.ts create mode 100644 src/modules/proxy-deployer/models/Minter.dto.ts create mode 100644 src/modules/proxy-deployer/models/MinterFilters.ts create mode 100644 src/modules/proxy-deployer/models/MintersResponse.ts create mode 100644 src/modules/proxy-deployer/models/index.ts create mode 100644 src/modules/proxy-deployer/models/requests/DeployMinterRequest.ts create mode 100644 src/modules/proxy-deployer/models/requests/whitelistMinterRequest.ts create mode 100644 src/modules/proxy-deployer/proxy-deployer-caching.service.ts create mode 100644 src/modules/proxy-deployer/proxy-deployer-mutations.resolver.ts create mode 100644 src/modules/proxy-deployer/proxy-deployer.abi.service.ts create mode 100644 src/modules/proxy-deployer/proxy-deployer.module.ts create mode 100644 src/modules/proxy-deployer/proxy-deployer.service.ts diff --git a/package-lock.json b/package-lock.json index 093724a21..327e26c37 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "@aws-sdk/lib-storage": "^3.438.0", "@elastic/elasticsearch": "7.12.0", "@golevelup/nestjs-rabbitmq": "4.0.0", - "@multiversx/sdk-core": "12.6.1", + "@multiversx/sdk-core": "12.14.0", "@multiversx/sdk-native-auth-server": "1.0.7", "@multiversx/sdk-nestjs-cache": "2.0.0-beta.2", "@multiversx/sdk-nestjs-common": "2.0.0-beta.2", @@ -3665,9 +3665,9 @@ } }, "node_modules/@multiversx/sdk-core": { - "version": "12.6.1", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-core/-/sdk-core-12.6.1.tgz", - "integrity": "sha512-T21TMC3euAi3C0WtB6WOzNYQW4XbKTrH0Q1K7gxcNpLDqnQbMwh0SuVAossQRL/s1Ca829Zjt3zmuGQUtWAU1A==", + "version": "12.14.0", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-core/-/sdk-core-12.14.0.tgz", + "integrity": "sha512-Y5cSD+o//Ngj0VYgQraPWbpRFgD0W3+IeVLGGsPP2PCoojA40m4sjgDMZkNIxuvWuy5BUQyx/pGFASPFLpvpJw==", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", "bech32": "1.1.4", @@ -3797,6 +3797,49 @@ "@nestjs/swagger": "^7.x" } }, + "node_modules/@multiversx/sdk-nestjs-common/node_modules/@multiversx/sdk-core": { + "version": "12.6.1", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-core/-/sdk-core-12.6.1.tgz", + "integrity": "sha512-T21TMC3euAi3C0WtB6WOzNYQW4XbKTrH0Q1K7gxcNpLDqnQbMwh0SuVAossQRL/s1Ca829Zjt3zmuGQUtWAU1A==", + "dependencies": { + "@multiversx/sdk-transaction-decoder": "1.0.2", + "bech32": "1.1.4", + "bignumber.js": "9.0.1", + "blake2b": "2.1.3", + "buffer": "6.0.3", + "json-duplicate-key-handle": "1.0.0", + "keccak": "3.0.2", + "protobufjs": "7.2.4" + } + }, + "node_modules/@multiversx/sdk-nestjs-common/node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + }, + "node_modules/@multiversx/sdk-nestjs-common/node_modules/protobufjs": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.4.tgz", + "integrity": "sha512-AT+RJgD2sH8phPmCf7OUZR8xGdcJRga4+1cOaXJ64hvcSkVhNcRHOwIxUatPH15+nj59WAGTDv3LSGZPEQbJaQ==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/@multiversx/sdk-nestjs-elastic": { "version": "2.0.0-beta.2", "resolved": "https://registry.npmjs.org/@multiversx/sdk-nestjs-elastic/-/sdk-nestjs-elastic-2.0.0-beta.2.tgz", diff --git a/package.json b/package.json index 7982b2992..67f240eba 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "@aws-sdk/lib-storage": "^3.438.0", "@elastic/elasticsearch": "7.12.0", "@golevelup/nestjs-rabbitmq": "4.0.0", - "@multiversx/sdk-core": "12.6.1", + "@multiversx/sdk-core": "12.14.0", "@multiversx/sdk-native-auth-server": "1.0.7", "@multiversx/sdk-nestjs-cache": "2.0.0-beta.2", "@multiversx/sdk-nestjs-common": "2.0.0-beta.2", diff --git a/schema.gql b/schema.gql index 6d83c12a2..1c26ab5db 100644 --- a/schema.gql +++ b/schema.gql @@ -697,6 +697,13 @@ input DeployMinterArgs { royaltiesClaimAddress: String! } +input DeployMinterArgsP { + maxNftsPerTransaction: Int! + mintClaimAddress: String! + ownerAddress: String! + royaltiesClaimAddress: String! +} + type ExploreCollectionsStats { activeLast30DaysCount: Int! allCollectionsCount: Int! @@ -977,6 +984,7 @@ type Mutation { deployMinter(input: DeployMinterArgs!): TransactionNode! disableMarketplace(input: UpdateMarketplaceStateArgs!): Boolean! enableMarketplace(input: UpdateMarketplaceStateArgs!): Boolean! + deployMinterP(input: DeployMinterArgsP!): TransactionNode! endAuction(auctionId: Int!): TransactionNode! flagCollection(input: FlagCollectionInput!): Boolean! flagNft(input: FlagNftInput!): Boolean! @@ -1553,4 +1561,4 @@ input WhitelistMarketplaceArgs { input WhitelistMinterArgs { address: String! adminAddress: String! -} \ No newline at end of file +} diff --git a/src/abis/proxy-deployer.abi.json b/src/abis/proxy-deployer.abi.json new file mode 100644 index 000000000..05d7eba08 --- /dev/null +++ b/src/abis/proxy-deployer.abi.json @@ -0,0 +1,150 @@ +{ + "buildInfo": { + "rustc": { + "version": "1.71.0-nightly", + "commitHash": "7f94b314cead7059a71a265a8b64905ef2511796", + "commitDate": "2023-04-23", + "channel": "Nightly", + "short": "rustc 1.71.0-nightly (7f94b314c 2023-04-23)" + }, + "contractCrate": { + "name": "proxy-deployer", + "version": "0.0.0" + }, + "framework": { + "name": "multiversx-sc", + "version": "0.43.4" + } + }, + "name": "ProxyDeployer", + "constructor": { + "inputs": [], + "outputs": [] + }, + "endpoints": [ + { + "name": "upgrade", + "mutability": "mutable", + "inputs": [], + "outputs": [] + }, + { + "name": "contractDeploy", + "mutability": "mutable", + "inputs": [ + { + "name": "template_address_id", + "type": "u64" + }, + { + "name": "args", + "type": "variadic", + "multi_arg": true + } + ], + "outputs": [ + { + "type": "Address" + } + ] + }, + { + "name": "contractUpgrade", + "mutability": "mutable", + "inputs": [ + { + "name": "contract_address", + "type": "Address" + }, + { + "name": "template_address_id", + "type": "u64" + }, + { + "name": "args", + "type": "variadic", + "multi_arg": true + } + ], + "outputs": [] + }, + { + "name": "callContractEndpoint", + "mutability": "mutable", + "inputs": [ + { + "name": "contract_address", + "type": "Address" + }, + { + "name": "function_name", + "type": "bytes" + }, + { + "name": "args", + "type": "variadic", + "multi_arg": true + } + ], + "outputs": [] + }, + { + "name": "addContractTemplate", + "onlyOwner": true, + "mutability": "mutable", + "inputs": [ + { + "name": "template_address", + "type": "Address" + } + ], + "outputs": [ + { + "type": "u64" + } + ] + }, + { + "name": "removeContractTemplate", + "onlyOwner": true, + "mutability": "mutable", + "inputs": [ + { + "name": "address_id", + "type": "u64" + } + ], + "outputs": [] + }, + { + "name": "getAllDeployers", + "mutability": "readonly", + "inputs": [], + "outputs": [ + { + "type": "variadic
", + "multi_result": true + } + ] + }, + { + "name": "getDeployerContractAddresses", + "mutability": "readonly", + "inputs": [ + { + "name": "deployer_address", + "type": "Address" + } + ], + "outputs": [ + { + "type": "variadic
", + "multi_result": true + } + ] + } + ], + "events": [], + "hasCallback": false, + "types": {} +} diff --git a/src/app.module.ts b/src/app.module.ts index 9a3f2a66a..4cbb5743f 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -40,6 +40,7 @@ import '@multiversx/sdk-nestjs-common/lib/utils/extensions/number.extensions'; import { TimescaleDbModule } from './common/persistence/timescaledb/timescaledb.module'; import { MintersModuleGraph } from './modules/minters/minters.module'; import { PersistenceModule } from './common/persistence/persistence.module'; +import { ProxyDeployerModuleGraph } from './modules/proxy-deployer/proxy-deployer.module'; @Module({ imports: [ @@ -99,6 +100,7 @@ import { PersistenceModule } from './common/persistence/persistence.module'; ExploreStatsModuleGraph, TimescaleDbModule, MintersModuleGraph, + ProxyDeployerModuleGraph, ], }) export class AppModule {} diff --git a/src/modules/auctions/contractLoader.ts b/src/modules/auctions/contractLoader.ts index daf5f42f3..ad883ac41 100644 --- a/src/modules/auctions/contractLoader.ts +++ b/src/modules/auctions/contractLoader.ts @@ -27,8 +27,10 @@ export class ContractLoader { try { const jsonContent: string = await fs.promises.readFile(this.abiPath, { encoding: 'utf8' }); const json = JSON.parse(jsonContent); + console.log({ json: JSON.stringify(json) }); const abiRegistry = AbiRegistry.create(json); + console.log(abiRegistry.getEndpoint('contractDeploy')); return abiRegistry; } catch (error) { diff --git a/src/modules/auctions/marketplaceUtils.ts b/src/modules/auctions/marketplaceUtils.ts index e1fbf9dc3..66956146a 100644 --- a/src/modules/auctions/marketplaceUtils.ts +++ b/src/modules/auctions/marketplaceUtils.ts @@ -6,6 +6,7 @@ export class MarketplaceUtils { public static readonly xoxnoMarketplaceAbiPath: string = './src/abis/xoxno-nft-marketplace.abi.json'; public static readonly deployerMintersAbiPath: string = './src/abis/nft-minter-deployer.abi.json'; + public static readonly proxyDeployerMintersAbiPath: string = './src/abis/proxy-deployer.abi.json'; static isExternalMarketplace(type: MarketplaceTypeEnum) { return type === MarketplaceTypeEnum.External; } diff --git a/src/modules/proxy-deployer/models/AddMinterArgs.ts b/src/modules/proxy-deployer/models/AddMinterArgs.ts new file mode 100644 index 000000000..a060dd3bc --- /dev/null +++ b/src/modules/proxy-deployer/models/AddMinterArgs.ts @@ -0,0 +1,14 @@ +import { Field, InputType, Int } from '@nestjs/graphql'; +import { Matches } from 'class-validator'; +import { ADDRESS_ERROR, ADDRESS_RGX } from 'src/utils/constants'; + +@InputType() +export class WhitelistMinterArgs { + @Matches(RegExp(ADDRESS_RGX), { message: ADDRESS_ERROR }) + @Field() + address: string; + + @Matches(RegExp(ADDRESS_RGX), { message: ADDRESS_ERROR }) + @Field() + adminAddress: string; +} diff --git a/src/modules/proxy-deployer/models/DeployMinterArgs.ts b/src/modules/proxy-deployer/models/DeployMinterArgs.ts new file mode 100644 index 000000000..f223d4771 --- /dev/null +++ b/src/modules/proxy-deployer/models/DeployMinterArgs.ts @@ -0,0 +1,28 @@ +import { Field, InputType, Int } from '@nestjs/graphql'; +import { Matches } from 'class-validator'; +import { ADDRESS_ERROR, ADDRESS_RGX } from 'src/utils/constants'; + +@InputType() +export class DeployMinterArgsP { + @Matches(RegExp(ADDRESS_RGX), { message: ADDRESS_ERROR }) + @Field() + royaltiesClaimAddress: string; + + @Matches(RegExp(ADDRESS_RGX), { message: ADDRESS_ERROR }) + @Field() + ownerAddress: string; + + @Matches(RegExp(ADDRESS_RGX), { message: ADDRESS_ERROR }) + @Field() + mintClaimAddress: string; + + @Field(() => Int) + maxNftsPerTransaction: number; +} + +@InputType() +export class UpgradeMinterArgs { + @Matches(RegExp(ADDRESS_RGX), { message: ADDRESS_ERROR }) + @Field() + minterAddress: string; +} diff --git a/src/modules/proxy-deployer/models/Minter.dto.ts b/src/modules/proxy-deployer/models/Minter.dto.ts new file mode 100644 index 000000000..7f15176ab --- /dev/null +++ b/src/modules/proxy-deployer/models/Minter.dto.ts @@ -0,0 +1,24 @@ +import { Field, ID, ObjectType } from '@nestjs/graphql'; +import { MinterEntity } from 'src/db/minters'; + +@ObjectType() +export class Minter { + @Field(() => ID) + address!: string; + + @Field(() => ID) + adminAddress!: string; + + constructor(init?: Partial) { + Object.assign(this, init); + } + + static fromEntity(minter: MinterEntity) { + return minter + ? new Minter({ + address: minter.address, + adminAddress: minter.adminAddress, + }) + : null; + } +} diff --git a/src/modules/proxy-deployer/models/MinterFilters.ts b/src/modules/proxy-deployer/models/MinterFilters.ts new file mode 100644 index 000000000..d5e7bc000 --- /dev/null +++ b/src/modules/proxy-deployer/models/MinterFilters.ts @@ -0,0 +1,18 @@ +import { Field, InputType, Int } from '@nestjs/graphql'; +import { Matches } from 'class-validator'; +import { ADDRESS_ERROR, ADDRESS_RGX } from 'src/utils/constants'; + +@InputType() +export class MinterFilters { + @Matches(RegExp(ADDRESS_RGX), { message: ADDRESS_ERROR }) + @Field() + minterAddress: string; + + @Matches(RegExp(ADDRESS_RGX), { message: ADDRESS_ERROR }) + @Field() + minterAdminAddress: string; + + constructor(init?: Partial) { + Object.assign(this, init); + } +} diff --git a/src/modules/proxy-deployer/models/MintersResponse.ts b/src/modules/proxy-deployer/models/MintersResponse.ts new file mode 100644 index 000000000..fee79fa0d --- /dev/null +++ b/src/modules/proxy-deployer/models/MintersResponse.ts @@ -0,0 +1,6 @@ +import { ObjectType } from '@nestjs/graphql'; +import relayTypes from 'src/modules/common/Relay.types'; +import { Minter } from './Minter.dto'; + +@ObjectType() +export class MintersResponse extends relayTypes(Minter) {} diff --git a/src/modules/proxy-deployer/models/index.ts b/src/modules/proxy-deployer/models/index.ts new file mode 100644 index 000000000..283d1f663 --- /dev/null +++ b/src/modules/proxy-deployer/models/index.ts @@ -0,0 +1,2 @@ +export * from './Minter.dto'; +export * from './AddMinterArgs'; diff --git a/src/modules/proxy-deployer/models/requests/DeployMinterRequest.ts b/src/modules/proxy-deployer/models/requests/DeployMinterRequest.ts new file mode 100644 index 000000000..8865dd921 --- /dev/null +++ b/src/modules/proxy-deployer/models/requests/DeployMinterRequest.ts @@ -0,0 +1,34 @@ +import { DeployMinterArgsP, UpgradeMinterArgs } from '../DeployMinterArgs'; + +export class DeployMinterRequest { + royaltiesClaimAddress: string; + mintClaimAddress: string; + ownerAddress: string; + maxNftsPerTransaction: number; + constructor(init?: Partial) { + Object.assign(this, init); + } + + static fromArgs(args: DeployMinterArgsP) { + return new DeployMinterRequest({ + royaltiesClaimAddress: args.royaltiesClaimAddress, + mintClaimAddress: args.mintClaimAddress, + maxNftsPerTransaction: args.maxNftsPerTransaction, + ownerAddress: args.ownerAddress, + }); + } +} + +export class UpgradeMinterRequest { + minterAddress: string; + + constructor(init?: Partial) { + Object.assign(this, init); + } + + static fromArgs(args: UpgradeMinterArgs) { + return new UpgradeMinterRequest({ + minterAddress: args.minterAddress, + }); + } +} diff --git a/src/modules/proxy-deployer/models/requests/whitelistMinterRequest.ts b/src/modules/proxy-deployer/models/requests/whitelistMinterRequest.ts new file mode 100644 index 000000000..1cfc76bd0 --- /dev/null +++ b/src/modules/proxy-deployer/models/requests/whitelistMinterRequest.ts @@ -0,0 +1,16 @@ +import { WhitelistMinterArgs } from '../AddMinterArgs'; + +export class WhitelistMinterRequest { + address: string; + adminAddress: string; + constructor(init?: Partial) { + Object.assign(this, init); + } + + static fromArgs(args: WhitelistMinterArgs) { + return new WhitelistMinterRequest({ + address: args.address, + adminAddress: args.adminAddress, + }); + } +} diff --git a/src/modules/proxy-deployer/proxy-deployer-caching.service.ts b/src/modules/proxy-deployer/proxy-deployer-caching.service.ts new file mode 100644 index 000000000..f1f7b4cd0 --- /dev/null +++ b/src/modules/proxy-deployer/proxy-deployer-caching.service.ts @@ -0,0 +1,18 @@ +import { Injectable } from '@nestjs/common'; +import '../../utils/extensions'; +import { RedisCacheService } from '@multiversx/sdk-nestjs-cache'; +import { CacheInfo } from 'src/common/services/caching/entities/cache.info'; +import { MinterEntity } from 'src/db/minters'; + +@Injectable() +export class MintersCachingService { + constructor(private redisCacheService: RedisCacheService) {} + + public async getMinters(getMinters: () => any): Promise { + return await this.redisCacheService.getOrSet(CacheInfo.Minters.key, () => getMinters(), CacheInfo.Minters.ttl); + } + + public async invalidateMinters() { + await this.redisCacheService.delete(CacheInfo.Minters.key); + } +} diff --git a/src/modules/proxy-deployer/proxy-deployer-mutations.resolver.ts b/src/modules/proxy-deployer/proxy-deployer-mutations.resolver.ts new file mode 100644 index 000000000..ea7bfd885 --- /dev/null +++ b/src/modules/proxy-deployer/proxy-deployer-mutations.resolver.ts @@ -0,0 +1,37 @@ +import { Resolver, Args, Mutation } from '@nestjs/graphql'; +import { BaseResolver } from '../common/base.resolver'; +import { UseGuards } from '@nestjs/common'; +import { JwtOrNativeAuthGuard } from '../auth/jwt.or.native.auth-guard'; +import { GqlAdminAuthGuard } from '../auth/gql-admin.auth-guard'; +import { DeployMinterArgsP, UpgradeMinterArgs } from './models/DeployMinterArgs'; +import { DeployMinterRequest, UpgradeMinterRequest } from './models/requests/DeployMinterRequest'; +import { ProxyDeployerAbiService } from './proxy-deployer.abi.service'; +import { TransactionNode } from '../common/transaction'; +import { AuthUser } from '../auth/authUser'; +import { UserAuthResult } from '../auth/userAuthResult'; +import { MintersResponse } from './models/MintersResponse'; + +@Resolver(() => MintersResponse) +export class ProxyDeployerMutationsResolver extends BaseResolver(MintersResponse) { + constructor(private minterDeployerService: ProxyDeployerAbiService) { + super(); + } + + @Mutation(() => TransactionNode) + // @UseGuards(JwtOrNativeAuthGuard, GqlAdminAuthGuard) + async deployMinterP(@Args('input') input: DeployMinterArgsP): Promise { + return await this.minterDeployerService.deployMinter(DeployMinterRequest.fromArgs(input)); + } + + // @Mutation(() => TransactionNode) + // @UseGuards(JwtOrNativeAuthGuard, GqlAdminAuthGuard) + // async pauseMinter(@Args('input') input: UpgradeMinterArgs, @AuthUser() user: UserAuthResult): Promise { + // return await this.minterDeployerService.pauseNftMinter(user.address, UpgradeMinterRequest.fromArgs(input)); + // } + + // @Mutation(() => TransactionNode) + // @UseGuards(JwtOrNativeAuthGuard, GqlAdminAuthGuard) + // async resumeMinter(@Args('input') input: UpgradeMinterArgs, @AuthUser() user: UserAuthResult): Promise { + // return await this.minterDeployerService.resumeNftMinter(user.address, UpgradeMinterRequest.fromArgs(input)); + // } +} diff --git a/src/modules/proxy-deployer/proxy-deployer.abi.service.ts b/src/modules/proxy-deployer/proxy-deployer.abi.service.ts new file mode 100644 index 000000000..5dc429f50 --- /dev/null +++ b/src/modules/proxy-deployer/proxy-deployer.abi.service.ts @@ -0,0 +1,79 @@ +import { Injectable } from '@nestjs/common'; +import { + Address, + AddressValue, + BytesValue, + Interaction, + ResultsParser, + U32Value, + VariadicType, + VariadicValue, +} from '@multiversx/sdk-core/out'; +import { MarketplaceUtils } from '../auctions/marketplaceUtils'; +import { TransactionNode } from '../common/transaction'; +import { DeployMinterRequest, UpgradeMinterRequest } from './models/requests/DeployMinterRequest'; +import { mxConfig, gas } from 'src/config'; +import { MxProxyService } from 'src/common'; +import { ContractLoader } from '../auctions/contractLoader'; + +@Injectable() +export class ProxyDeployerAbiService { + private readonly parser: ResultsParser; + private contract = new ContractLoader(MarketplaceUtils.proxyDeployerMintersAbiPath); + + constructor(private mxProxyService: MxProxyService) { + this.parser = new ResultsParser(); + } + + async deployMinter(request: DeployMinterRequest): Promise { + const contract = await this.contract.getContract(process.env.DEPLOYER_ADDRESS); + + return contract.methods + .contractDeploy([1, request.royaltiesClaimAddress, request.mintClaimAddress, request.maxNftsPerTransaction]) + .check() + .withChainID(mxConfig.chainID) + .withGasLimit(gas.deployMinter) + .withSender(Address.fromString(request.ownerAddress)) + .buildTransaction() + .toPlainObject(); + } + + async pauseNftMinter(ownerAddress: string, request: UpgradeMinterRequest): Promise { + const contract = await this.contract.getContract(process.env.DEPLOYER_ADDRESS); + + return contract.methodsExplicit + .pauseNftMinter([new AddressValue(new Address(request.minterAddress))]) + .withChainID(mxConfig.chainID) + .withGasLimit(gas.deployMinter) + .withSender(Address.fromString(ownerAddress)) + .buildTransaction() + .toPlainObject(); + } + + async resumeNftMinter(ownerAddress: string, request: UpgradeMinterRequest): Promise { + const contract = await this.contract.getContract(process.env.DEPLOYER_ADDRESS); + + return contract.methodsExplicit + .resumeNftMinter([new AddressValue(new Address(request.minterAddress))]) + .withChainID(mxConfig.chainID) + .withSender(Address.fromString(ownerAddress)) + .withGasLimit(gas.deployMinter) + .buildTransaction() + .toPlainObject(); + } + + public async getMintersForAddress(address: string): Promise { + const contract = await this.contract.getContract(process.env.DEPLOYER_ADDRESS); + let getDataQuery = contract.methodsExplicit.getUserNftMinterContracts([new AddressValue(new Address(address))]); + + const response = await this.getFirstQueryResult(getDataQuery); + const contractAddresses: AddressValue[] = response?.firstValue?.valueOf(); + return contractAddresses.map((x) => x.valueOf().bech32()); + } + + private async getFirstQueryResult(interaction: Interaction) { + let queryResponse = await this.mxProxyService.getService().queryContract(interaction.buildQuery()); + let result = this.parser.parseQueryResponse(queryResponse, interaction.getEndpoint()); + return result; + } +} diff --git a/src/modules/proxy-deployer/proxy-deployer.module.ts b/src/modules/proxy-deployer/proxy-deployer.module.ts new file mode 100644 index 000000000..8df09d89f --- /dev/null +++ b/src/modules/proxy-deployer/proxy-deployer.module.ts @@ -0,0 +1,17 @@ +import { forwardRef, Module } from '@nestjs/common'; +import { MxCommunicationModule } from 'src/common'; +import { ProxyDeployerMutationsResolver } from './proxy-deployer-mutations.resolver'; +import { MintersService } from './proxy-deployer.service'; +import { PubSubListenerModule } from 'src/pubsub/pub.sub.listener.module'; +import { CommonModule } from 'src/common.module'; +import { AuthModule } from '../auth/auth.module'; +import { MintersCachingService } from './proxy-deployer-caching.service'; +import { ProxyDeployerAbiService } from './proxy-deployer.abi.service'; +import { CacheEventsPublisherModule } from '../rabbitmq/cache-invalidation/cache-invalidation-publisher/change-events-publisher.module'; + +@Module({ + providers: [ProxyDeployerMutationsResolver, MintersService, MintersCachingService, ProxyDeployerAbiService], + imports: [PubSubListenerModule, MxCommunicationModule, CommonModule, forwardRef(() => AuthModule), CacheEventsPublisherModule], + exports: [MintersService, MintersCachingService], +}) +export class ProxyDeployerModuleGraph {} diff --git a/src/modules/proxy-deployer/proxy-deployer.service.ts b/src/modules/proxy-deployer/proxy-deployer.service.ts new file mode 100644 index 000000000..a84a23d3c --- /dev/null +++ b/src/modules/proxy-deployer/proxy-deployer.service.ts @@ -0,0 +1,81 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { Minter } from './models'; +import { PersistenceService } from 'src/common/persistence/persistence.service'; +import { MinterEntity } from 'src/db/minters'; +import { UnableToLoadError } from 'src/common/models/errors/unable-to-load-error'; +import { MintersCachingService } from './proxy-deployer-caching.service'; +import { WhitelistMinterRequest } from './models/requests/whitelistMinterRequest'; +import { MinterFilters } from './models/MinterFilters'; +import { ProxyDeployerAbiService } from './proxy-deployer.abi.service'; +import { CacheEventsPublisherService } from '../rabbitmq/cache-invalidation/cache-invalidation-publisher/change-events-publisher.service'; +import { ChangedEvent, CacheEventTypeEnum } from '../rabbitmq/cache-invalidation/events/changed.event'; + +@Injectable() +export class MintersService { + constructor( + private persistenceService: PersistenceService, + private cacheService: MintersCachingService, + private minterDeployerService: ProxyDeployerAbiService, + private readonly cacheEventsPublisher: CacheEventsPublisherService, + private readonly logger: Logger, + ) {} + + async whitelistMinter(request: WhitelistMinterRequest): Promise { + try { + const contractAddresses = await this.minterDeployerService.getMintersForAddress(request.adminAddress); + if (contractAddresses.includes(request.address)) { + const savedMinter = await this.persistenceService.saveMinter(MinterEntity.fromRequest(request)); + await this.triggerCacheInvalidation(); + return savedMinter ? true : false; + } + return false; + } catch (error) { + this.logger.error('An error has occured while saving the minter ', { + path: this.whitelistMinter.name, + minterAddress: request?.address, + exception: error, + }); + throw new UnableToLoadError(`An error has ocurred while saving the minter: ${request?.address}`); + } + } + + async getMinters(filters?: MinterFilters): Promise { + try { + let minters = await this.cacheService.getMinters(() => this.persistenceService.getMinters()); + if (filters) { + if (filters.minterAddress) minters = minters.filter((m) => m.address === filters.minterAddress); + if (filters.minterAdminAddress) minters = minters.filter((m) => m.adminAddress === filters.minterAdminAddress); + } + + return minters?.map((minter) => Minter.fromEntity(minter)); + } catch (error) { + this.logger.error('An error has occured while getting minters', { + path: this.getMinters.name, + exception: error, + filters, + }); + return []; + } + } + + async getMintersAddresses(): Promise { + try { + const minters = await this.getMinters(); + return minters?.map((x) => x.address); + } catch (error) { + this.logger.error('An error has occured while getting minters addresses', { + path: this.getMintersAddresses.name, + exception: error, + }); + return []; + } + } + + private async triggerCacheInvalidation(): Promise { + await this.cacheEventsPublisher.publish( + new ChangedEvent({ + type: CacheEventTypeEnum.Minters, + }), + ); + } +} From 6251ee4295a354c3c00739ee6ce2862606229afa Mon Sep 17 00:00:00 2001 From: danielailie Date: Mon, 11 Dec 2023 11:41:11 +0200 Subject: [PATCH 02/11] Add deploy marketplace and bulk contracts --- .jest/setEnvVars.js | 2 + schema.gql | 18 +- src/abis/proxy-deployer.abi.json | 159 ++++++++++++++++-- .../proxy-deployer/models/DeployBulkArgs.ts | 19 +++ .../models/DeployMarketplaceArgs.ts | 27 +++ .../proxy-deployer-mutations.resolver.ts | 20 ++- .../proxy-deployer.abi.service.ts | 28 ++- 7 files changed, 252 insertions(+), 21 deletions(-) create mode 100644 src/modules/proxy-deployer/models/DeployBulkArgs.ts create mode 100644 src/modules/proxy-deployer/models/DeployMarketplaceArgs.ts diff --git a/.jest/setEnvVars.js b/.jest/setEnvVars.js index 1370b9eae..7ad7bfde4 100644 --- a/.jest/setEnvVars.js +++ b/.jest/setEnvVars.js @@ -1 +1,3 @@ process.env.DEPLOYER_ADDRESS = 'erd1qqqqqqqqqqqqqpgqut6lamz9dn480ytj8cmcwvydcu3lj55epltq9t9kam'; +process.env.BULK_ADDRESS = 'erd1qqqqqqqqqqqqqpgqzs3y0vr4t4sqyet32t6jp9m85l3hlr93u00sdj9rxa'; +process.env.MARKETPLACE_ADDRESS = 'erd1qqqqqqqqqqqqqpgq9ac9zvc4ugzrgqaqjqgjdhvxxtx7wu2eu00sxezym3'; diff --git a/schema.gql b/schema.gql index 1c26ab5db..72287521f 100644 --- a/schema.gql +++ b/schema.gql @@ -690,6 +690,20 @@ enum CustomFiltersEnum { Tickets } +input DeployBulkArgs { + ownerAddress: String! +} + +input DeployMarketplaceArgs { + marketplaceFee: String! + ownerAddress: String! + + """ + The accepted payment tokens for auction on the marketplace. By default, if left empty, accepts all payment tokens + """ + paymentTokens: [String!] +} + input DeployMinterArgs { maxNftsPerTransaction: Int! mintClaimAddress: String! @@ -981,10 +995,12 @@ type Mutation { createAuction(input: CreateAuctionArgs!): TransactionNode! createNft(file: Upload!, input: CreateNftArgs!): TransactionNode! createNftWithMultipleFiles(files: [Upload!]!, input: CreateNftArgs!): TransactionNode! + deployBulkSmartContract(input: DeployBulkArgs!): TransactionNode! + deployMarketplaceContract(input: DeployMarketplaceArgs!): TransactionNode! deployMinter(input: DeployMinterArgs!): TransactionNode! disableMarketplace(input: UpdateMarketplaceStateArgs!): Boolean! enableMarketplace(input: UpdateMarketplaceStateArgs!): Boolean! - deployMinterP(input: DeployMinterArgsP!): TransactionNode! + deployMinterSmartContract(input: DeployMinterArgsP!): TransactionNode! endAuction(auctionId: Int!): TransactionNode! flagCollection(input: FlagCollectionInput!): Boolean! flagNft(input: FlagNftInput!): Boolean! diff --git a/src/abis/proxy-deployer.abi.json b/src/abis/proxy-deployer.abi.json index 05d7eba08..e245d5f26 100644 --- a/src/abis/proxy-deployer.abi.json +++ b/src/abis/proxy-deployer.abi.json @@ -13,12 +13,17 @@ }, "framework": { "name": "multiversx-sc", - "version": "0.43.4" + "version": "0.44.0" } }, "name": "ProxyDeployer", "constructor": { - "inputs": [], + "inputs": [ + { + "name": "default_gas_for_save", + "type": "u64" + } + ], "outputs": [] }, "endpoints": [ @@ -33,8 +38,8 @@ "mutability": "mutable", "inputs": [ { - "name": "template_address_id", - "type": "u64" + "name": "template_address", + "type": "Address" }, { "name": "args", @@ -57,8 +62,8 @@ "type": "Address" }, { - "name": "template_address_id", - "type": "u64" + "name": "template_address", + "type": "Address" }, { "name": "args", @@ -69,7 +74,7 @@ "outputs": [] }, { - "name": "callContractEndpoint", + "name": "contractCallByAddress", "mutability": "mutable", "inputs": [ { @@ -89,33 +94,103 @@ "outputs": [] }, { - "name": "addContractTemplate", + "name": "upgradeContractsByTemplate", "onlyOwner": true, "mutability": "mutable", "inputs": [ { - "name": "template_address", - "type": "Address" + "name": "gas_per_action", + "type": "u64" + }, + { + "name": "opt_template_address", + "type": "optional
", + "multi_arg": true + }, + { + "name": "opt_args", + "type": "optional>", + "multi_arg": true } ], "outputs": [ { - "type": "u64" + "type": "bool" } - ] + ], + "allow_multiple_var_args": true + }, + { + "name": "addDeployerToBlacklist", + "onlyOwner": true, + "mutability": "mutable", + "inputs": [ + { + "name": "blacklisted_address", + "type": "Address" + } + ], + "outputs": [] + }, + { + "name": "removeDeployerFromBlacklist", + "onlyOwner": true, + "mutability": "mutable", + "inputs": [ + { + "name": "address", + "type": "Address" + } + ], + "outputs": [] }, { - "name": "removeContractTemplate", + "name": "setDefaultGasForSaveOperation", "onlyOwner": true, "mutability": "mutable", "inputs": [ { - "name": "address_id", + "name": "default_gas_for_save_operation", "type": "u64" } ], "outputs": [] }, + { + "name": "getAllDeployedContractsByTemplate", + "mutability": "readonly", + "inputs": [ + { + "name": "template_address", + "type": "Address" + } + ], + "outputs": [ + { + "type": "List
" + } + ] + }, + { + "name": "getOngoingUpgradeOperations", + "mutability": "readonly", + "inputs": [], + "outputs": [ + { + "type": "OngoingUpgradeOperation" + } + ] + }, + { + "name": "getDefaultGasForSaveOperation", + "mutability": "readonly", + "inputs": [], + "outputs": [ + { + "type": "u64" + } + ] + }, { "name": "getAllDeployers", "mutability": "readonly", @@ -142,9 +217,63 @@ "multi_result": true } ] + }, + { + "name": "getAllBlacklistedDeployers", + "mutability": "readonly", + "inputs": [], + "outputs": [ + { + "type": "variadic
", + "multi_result": true + } + ] + }, + { + "name": "pause", + "onlyOwner": true, + "mutability": "mutable", + "inputs": [], + "outputs": [] + }, + { + "name": "unpause", + "onlyOwner": true, + "mutability": "mutable", + "inputs": [], + "outputs": [] + }, + { + "name": "isPaused", + "mutability": "readonly", + "inputs": [], + "outputs": [ + { + "type": "bool" + } + ] } ], "events": [], + "esdtAttributes": [], "hasCallback": false, - "types": {} + "types": { + "OngoingUpgradeOperation": { + "type": "struct", + "fields": [ + { + "name": "template_address", + "type": "Address" + }, + { + "name": "arguments", + "type": "List" + }, + { + "name": "contracts_remaining", + "type": "List
" + } + ] + } + } } diff --git a/src/modules/proxy-deployer/models/DeployBulkArgs.ts b/src/modules/proxy-deployer/models/DeployBulkArgs.ts new file mode 100644 index 000000000..aa520d6ca --- /dev/null +++ b/src/modules/proxy-deployer/models/DeployBulkArgs.ts @@ -0,0 +1,19 @@ +import { Field, InputType, Int } from '@nestjs/graphql'; +import { Matches } from 'class-validator'; +import { ADDRESS_ERROR, ADDRESS_RGX } from 'src/utils/constants'; + +@InputType() +export class DeployBulkArgs { + @Matches(RegExp(ADDRESS_RGX), { message: ADDRESS_ERROR }) + @Field() + ownerAddress: string; + + maxNftsPerTransaction: number; +} + +@InputType() +export class UpgradeMinterArgs { + @Matches(RegExp(ADDRESS_RGX), { message: ADDRESS_ERROR }) + @Field() + minterAddress: string; +} diff --git a/src/modules/proxy-deployer/models/DeployMarketplaceArgs.ts b/src/modules/proxy-deployer/models/DeployMarketplaceArgs.ts new file mode 100644 index 000000000..575bbe20f --- /dev/null +++ b/src/modules/proxy-deployer/models/DeployMarketplaceArgs.ts @@ -0,0 +1,27 @@ +import { Field, InputType } from '@nestjs/graphql'; +import { Matches } from 'class-validator'; +import { ADDRESS_ERROR, ADDRESS_RGX, NUMERIC_ERROR, NUMERIC_RGX } from 'src/utils/constants'; + +@InputType() +export class DeployMarketplaceArgs { + @Matches(RegExp(ADDRESS_RGX), { message: ADDRESS_ERROR }) + @Field() + ownerAddress: string; + + @Field() + @Matches(RegExp(NUMERIC_RGX), { message: `Marketplace fee ${NUMERIC_ERROR}` }) + marketplaceFee: string; + + @Field(() => [String], { + description: 'The accepted payment tokens for auction on the marketplace. By default, if left empty, accepts all payment tokens', + nullable: true, + }) + paymentTokens: string[]; +} + +@InputType() +export class UpgradeMinterArgs { + @Matches(RegExp(ADDRESS_RGX), { message: ADDRESS_ERROR }) + @Field() + minterAddress: string; +} diff --git a/src/modules/proxy-deployer/proxy-deployer-mutations.resolver.ts b/src/modules/proxy-deployer/proxy-deployer-mutations.resolver.ts index ea7bfd885..03210e71b 100644 --- a/src/modules/proxy-deployer/proxy-deployer-mutations.resolver.ts +++ b/src/modules/proxy-deployer/proxy-deployer-mutations.resolver.ts @@ -7,9 +7,9 @@ import { DeployMinterArgsP, UpgradeMinterArgs } from './models/DeployMinterArgs' import { DeployMinterRequest, UpgradeMinterRequest } from './models/requests/DeployMinterRequest'; import { ProxyDeployerAbiService } from './proxy-deployer.abi.service'; import { TransactionNode } from '../common/transaction'; -import { AuthUser } from '../auth/authUser'; -import { UserAuthResult } from '../auth/userAuthResult'; import { MintersResponse } from './models/MintersResponse'; +import { DeployBulkArgs } from './models/DeployBulkArgs'; +import { DeployMarketplaceArgs } from './models/DeployMarketplaceArgs'; @Resolver(() => MintersResponse) export class ProxyDeployerMutationsResolver extends BaseResolver(MintersResponse) { @@ -19,8 +19,20 @@ export class ProxyDeployerMutationsResolver extends BaseResolver(MintersResponse @Mutation(() => TransactionNode) // @UseGuards(JwtOrNativeAuthGuard, GqlAdminAuthGuard) - async deployMinterP(@Args('input') input: DeployMinterArgsP): Promise { - return await this.minterDeployerService.deployMinter(DeployMinterRequest.fromArgs(input)); + async deployMinterSmartContract(@Args('input') input: DeployMinterArgsP): Promise { + return await this.minterDeployerService.deployMinterSc(DeployMinterRequest.fromArgs(input)); + } + + @Mutation(() => TransactionNode) + // @UseGuards(JwtOrNativeAuthGuard, GqlAdminAuthGuard) + async deployBulkSmartContract(@Args('input') input: DeployBulkArgs): Promise { + return await this.minterDeployerService.deployBulkSc(input.ownerAddress); + } + + @Mutation(() => TransactionNode) + // @UseGuards(JwtOrNativeAuthGuard, GqlAdminAuthGuard) + async deployMarketplaceContract(@Args('input') input: DeployMarketplaceArgs): Promise { + return await this.minterDeployerService.deployBulkSc(input.ownerAddress); } // @Mutation(() => TransactionNode) diff --git a/src/modules/proxy-deployer/proxy-deployer.abi.service.ts b/src/modules/proxy-deployer/proxy-deployer.abi.service.ts index 5dc429f50..6dd30e6a2 100644 --- a/src/modules/proxy-deployer/proxy-deployer.abi.service.ts +++ b/src/modules/proxy-deployer/proxy-deployer.abi.service.ts @@ -25,7 +25,7 @@ export class ProxyDeployerAbiService { this.parser = new ResultsParser(); } - async deployMinter(request: DeployMinterRequest): Promise { + async deployMinterSc(request: DeployMinterRequest): Promise { const contract = await this.contract.getContract(process.env.DEPLOYER_ADDRESS); return contract.methods @@ -38,6 +38,32 @@ export class ProxyDeployerAbiService { .toPlainObject(); } + async deployBulkSc(ownerAddress: string): Promise { + const contract = await this.contract.getContract(process.env.BULK_ADDRESS); + + return contract.methods + .contractDeploy([ownerAddress]) + .check() + .withChainID(mxConfig.chainID) + .withGasLimit(gas.deployMinter) + .withSender(Address.fromString(ownerAddress)) + .buildTransaction() + .toPlainObject(); + } + + async deployMarketplaceSc(ownerAddress: string, marketplaceFee: string, paymentTokens?: string[]): Promise { + const contract = await this.contract.getContract(process.env.BULK_ADDRESS); + + return contract.methods + .contractDeploy([marketplaceFee, paymentTokens]) + .check() + .withChainID(mxConfig.chainID) + .withGasLimit(gas.deployMinter) + .withSender(Address.fromString(ownerAddress)) + .buildTransaction() + .toPlainObject(); + } + async pauseNftMinter(ownerAddress: string, request: UpgradeMinterRequest): Promise { const contract = await this.contract.getContract(process.env.DEPLOYER_ADDRESS); From 9f6a64620bef7e2a3be8693e4e008985262896e9 Mon Sep 17 00:00:00 2001 From: danielailie Date: Mon, 11 Dec 2023 13:51:39 +0200 Subject: [PATCH 03/11] Update deploy contracts --- .../proxy-deployer.abi.service.ts | 41 ++++++++++--------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/src/modules/proxy-deployer/proxy-deployer.abi.service.ts b/src/modules/proxy-deployer/proxy-deployer.abi.service.ts index 6dd30e6a2..32e93424f 100644 --- a/src/modules/proxy-deployer/proxy-deployer.abi.service.ts +++ b/src/modules/proxy-deployer/proxy-deployer.abi.service.ts @@ -1,14 +1,5 @@ import { Injectable } from '@nestjs/common'; -import { - Address, - AddressValue, - BytesValue, - Interaction, - ResultsParser, - U32Value, - VariadicType, - VariadicValue, -} from '@multiversx/sdk-core/out'; +import { Address, AddressValue, BytesValue, Interaction, List, ResultsParser, U32Value, VariadicValue } from '@multiversx/sdk-core/out'; import { MarketplaceUtils } from '../auctions/marketplaceUtils'; import { TransactionNode } from '../common/transaction'; import { DeployMinterRequest, UpgradeMinterRequest } from './models/requests/DeployMinterRequest'; @@ -28,9 +19,16 @@ export class ProxyDeployerAbiService { async deployMinterSc(request: DeployMinterRequest): Promise { const contract = await this.contract.getContract(process.env.DEPLOYER_ADDRESS); - return contract.methods - .contractDeploy([1, request.royaltiesClaimAddress, request.mintClaimAddress, request.maxNftsPerTransaction]) - .check() + return contract.methodsExplicit + .contractDeploy([ + new AddressValue(Address.fromString(process.env.TEMPLATE_MINTER_ADDRESS)), + VariadicValue.fromItems( + BytesValue.fromHex(Address.fromString(request.royaltiesClaimAddress).hex()), + BytesValue.fromHex(Address.fromString(request.mintClaimAddress).hex()), + new U32Value(request.maxNftsPerTransaction), + BytesValue.fromHex(Address.fromString(request.ownerAddress).hex()), + ), + ]) .withChainID(mxConfig.chainID) .withGasLimit(gas.deployMinter) .withSender(Address.fromString(request.ownerAddress)) @@ -39,11 +37,13 @@ export class ProxyDeployerAbiService { } async deployBulkSc(ownerAddress: string): Promise { - const contract = await this.contract.getContract(process.env.BULK_ADDRESS); + const contract = await this.contract.getContract(process.env.DEPLOYER_ADDRESS); - return contract.methods - .contractDeploy([ownerAddress]) - .check() + return contract.methodsExplicit + .contractDeploy([ + new AddressValue(Address.fromString(process.env.TEMPLATE_BULK_ADDRESS)), + VariadicValue.fromItems(BytesValue.fromHex(Address.fromString(ownerAddress).hex())), + ]) .withChainID(mxConfig.chainID) .withGasLimit(gas.deployMinter) .withSender(Address.fromString(ownerAddress)) @@ -52,10 +52,13 @@ export class ProxyDeployerAbiService { } async deployMarketplaceSc(ownerAddress: string, marketplaceFee: string, paymentTokens?: string[]): Promise { - const contract = await this.contract.getContract(process.env.BULK_ADDRESS); + const contract = await this.contract.getContract(process.env.TEMPLATE_MARKETPLACE_ADDRESS); return contract.methods - .contractDeploy([marketplaceFee, paymentTokens]) + .contractDeploy([ + new AddressValue(Address.fromString(process.env.TEMPLATE_MINTER_ADDRESS)), + VariadicValue.fromItems(new U32Value(marketplaceFee), List.fromItems(paymentTokens?.map((tag) => BytesValue.fromUTF8(tag)))), + ]) .check() .withChainID(mxConfig.chainID) .withGasLimit(gas.deployMinter) From 6f98daa48ea506ff7becb0c0d9c801c71f462651 Mon Sep 17 00:00:00 2001 From: danielailie Date: Mon, 11 Dec 2023 15:39:17 +0200 Subject: [PATCH 04/11] Add tests --- .jest/setEnvVars.js | 5 +- src/modules/auctions/contractLoader.ts | 2 - .../proxy-deployer.abi.service.ts | 15 +-- .../tests/proxy-deployer.abi.service.spec.ts | 97 +++++++++++++++++++ 4 files changed, 108 insertions(+), 11 deletions(-) create mode 100644 src/modules/proxy-deployer/tests/proxy-deployer.abi.service.spec.ts diff --git a/.jest/setEnvVars.js b/.jest/setEnvVars.js index 7ad7bfde4..9a9edd787 100644 --- a/.jest/setEnvVars.js +++ b/.jest/setEnvVars.js @@ -1,3 +1,4 @@ process.env.DEPLOYER_ADDRESS = 'erd1qqqqqqqqqqqqqpgqut6lamz9dn480ytj8cmcwvydcu3lj55epltq9t9kam'; -process.env.BULK_ADDRESS = 'erd1qqqqqqqqqqqqqpgqzs3y0vr4t4sqyet32t6jp9m85l3hlr93u00sdj9rxa'; -process.env.MARKETPLACE_ADDRESS = 'erd1qqqqqqqqqqqqqpgq9ac9zvc4ugzrgqaqjqgjdhvxxtx7wu2eu00sxezym3'; +process.env.TEMPLATE_BULK_ADDRESS = 'erd1qqqqqqqqqqqqqpgqzs3y0vr4t4sqyet32t6jp9m85l3hlr93u00sdj9rxa'; +process.env.TEMPLATE_MINTER_ADDRESS = 'erd1qqqqqqqqqqqqqpgqzs3y0vr4t4sqyet32t6jp9m85l3hlr93u00sdj9rxa'; +process.env.TEMPLATE_MARKETPLACE_ADDRESS = 'erd1qqqqqqqqqqqqqpgq9ac9zvc4ugzrgqaqjqgjdhvxxtx7wu2eu00sxezym3'; diff --git a/src/modules/auctions/contractLoader.ts b/src/modules/auctions/contractLoader.ts index ad883ac41..daf5f42f3 100644 --- a/src/modules/auctions/contractLoader.ts +++ b/src/modules/auctions/contractLoader.ts @@ -27,10 +27,8 @@ export class ContractLoader { try { const jsonContent: string = await fs.promises.readFile(this.abiPath, { encoding: 'utf8' }); const json = JSON.parse(jsonContent); - console.log({ json: JSON.stringify(json) }); const abiRegistry = AbiRegistry.create(json); - console.log(abiRegistry.getEndpoint('contractDeploy')); return abiRegistry; } catch (error) { diff --git a/src/modules/proxy-deployer/proxy-deployer.abi.service.ts b/src/modules/proxy-deployer/proxy-deployer.abi.service.ts index 32e93424f..3ea11f319 100644 --- a/src/modules/proxy-deployer/proxy-deployer.abi.service.ts +++ b/src/modules/proxy-deployer/proxy-deployer.abi.service.ts @@ -52,14 +52,15 @@ export class ProxyDeployerAbiService { } async deployMarketplaceSc(ownerAddress: string, marketplaceFee: string, paymentTokens?: string[]): Promise { - const contract = await this.contract.getContract(process.env.TEMPLATE_MARKETPLACE_ADDRESS); - - return contract.methods - .contractDeploy([ - new AddressValue(Address.fromString(process.env.TEMPLATE_MINTER_ADDRESS)), + const contract = await this.contract.getContract(process.env.DEPLOYER_ADDRESS); + const args: any[] = [new AddressValue(Address.fromString(process.env.TEMPLATE_MARKETPLACE_ADDRESS))]; + if (paymentTokens) { + args.push( VariadicValue.fromItems(new U32Value(marketplaceFee), List.fromItems(paymentTokens?.map((tag) => BytesValue.fromUTF8(tag)))), - ]) - .check() + ); + } + return contract.methods + .contractDeploy(args) .withChainID(mxConfig.chainID) .withGasLimit(gas.deployMinter) .withSender(Address.fromString(ownerAddress)) diff --git a/src/modules/proxy-deployer/tests/proxy-deployer.abi.service.spec.ts b/src/modules/proxy-deployer/tests/proxy-deployer.abi.service.spec.ts new file mode 100644 index 000000000..c309371d8 --- /dev/null +++ b/src/modules/proxy-deployer/tests/proxy-deployer.abi.service.spec.ts @@ -0,0 +1,97 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { DeployMinterRequest, UpgradeMinterRequest } from '../models/requests/DeployMinterRequest'; +import { MxProxyService } from 'src/common'; +import { ProxyDeployerAbiService } from '../proxy-deployer.abi.service'; + +describe('Proxy Deployer Abi Service', () => { + let service: ProxyDeployerAbiService; + let module: TestingModule; + + beforeEach(async () => { + module = await Test.createTestingModule({ + providers: [ + ProxyDeployerAbiService, + { + provide: MxProxyService, + useValue: {}, + }, + ], + }).compile(); + + service = module.get(ProxyDeployerAbiService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); + + describe('deployMinterSc', () => { + it('returns built transaction with right arguments', async () => { + const result = await service.deployMinterSc( + new DeployMinterRequest({ + maxNftsPerTransaction: 4, + mintClaimAddress: 'erd1dc3yzxxeq69wvf583gw0h67td226gu2ahpk3k50qdgzzym8npltq7ndgha', + royaltiesClaimAddress: 'erd1dc3yzxxeq69wvf583gw0h67td226gu2ahpk3k50qdgzzym8npltq7ndgha', + ownerAddress: 'erd1dc3yzxxeq69wvf583gw0h67td226gu2ahpk3k50qdgzzym8npltq7ndgha', + }), + ); + + const expectedResult = { + chainID: 'T', + data: 'Y29udHJhY3REZXBsb3lAMDAwMDAwMDAwMDAwMDAwMDA1MDAxNDIyNDdiMDc1NWQ2MDAyNjU3MTUyZjUyMDk3NjdhN2UzN2Y4Y2IxZTNkZkA2ZTIyNDExOGQ5MDY4YWU2MjY4NzhhMWNmYmViY2I2YTk1YTQ3MTVkYjg2ZDFiNTFlMDZhMDQyMjZjZjMwZmQ2QDZlMjI0MTE4ZDkwNjhhZTYyNjg3OGExY2ZiZWJjYjZhOTVhNDcxNWRiODZkMWI1MWUwNmEwNDIyNmNmMzBmZDZAMDRANmUyMjQxMThkOTA2OGFlNjI2ODc4YTFjZmJlYmNiNmE5NWE0NzE1ZGI4NmQxYjUxZTA2YTA0MjI2Y2YzMGZkNg==', + gasLimit: 70000000, + gasPrice: 1000000000, + nonce: 0, + options: undefined, + receiver: 'erd1qqqqqqqqqqqqqpgqut6lamz9dn480ytj8cmcwvydcu3lj55epltq9t9kam', + sender: 'erd1dc3yzxxeq69wvf583gw0h67td226gu2ahpk3k50qdgzzym8npltq7ndgha', + signature: undefined, + value: '0', + version: 1, + }; + expect(result).toMatchObject(expectedResult); + }); + }); + + describe('deployBulkSc', () => { + it('returns built transaction with right arguments', async () => { + const result = await service.deployBulkSc('erd1dc3yzxxeq69wvf583gw0h67td226gu2ahpk3k50qdgzzym8npltq7ndgha'); + + const expectedResult = { + chainID: 'T', + data: 'Y29udHJhY3REZXBsb3lAMDAwMDAwMDAwMDAwMDAwMDA1MDAxNDIyNDdiMDc1NWQ2MDAyNjU3MTUyZjUyMDk3NjdhN2UzN2Y4Y2IxZTNkZkA2ZTIyNDExOGQ5MDY4YWU2MjY4NzhhMWNmYmViY2I2YTk1YTQ3MTVkYjg2ZDFiNTFlMDZhMDQyMjZjZjMwZmQ2', + gasLimit: 70000000, + gasPrice: 1000000000, + nonce: 0, + options: undefined, + receiver: 'erd1qqqqqqqqqqqqqpgqut6lamz9dn480ytj8cmcwvydcu3lj55epltq9t9kam', + sender: 'erd1dc3yzxxeq69wvf583gw0h67td226gu2ahpk3k50qdgzzym8npltq7ndgha', + signature: undefined, + value: '0', + version: 1, + }; + expect(result).toMatchObject(expectedResult); + }); + }); + + describe('deployMarketplaceSc', () => { + it('returns built transaction with right arguments', async () => { + const result = await service.deployMarketplaceSc('erd1dc3yzxxeq69wvf583gw0h67td226gu2ahpk3k50qdgzzym8npltq7ndgha', '10000'); + + const expectedResult = { + chainID: 'T', + data: 'Y29udHJhY3REZXBsb3lAMDAwMDAwMDAwMDAwMDAwMDA1MDAyZjcwNTEzMzE1ZTIwNDM0MDNhMDkwMTEyNmRkODYzMmNkZTc3MTU5ZTNkZg==', + gasLimit: 70000000, + gasPrice: 1000000000, + nonce: 0, + options: undefined, + receiver: 'erd1qqqqqqqqqqqqqpgqut6lamz9dn480ytj8cmcwvydcu3lj55epltq9t9kam', + sender: 'erd1dc3yzxxeq69wvf583gw0h67td226gu2ahpk3k50qdgzzym8npltq7ndgha', + signature: undefined, + value: '0', + version: 1, + }; + expect(result).toMatchObject(expectedResult); + }); + }); +}); From d3a38040edbccea5786c36e140ccef1bd5ec358f Mon Sep 17 00:00:00 2001 From: danielailie Date: Mon, 11 Dec 2023 21:29:42 +0200 Subject: [PATCH 05/11] Add tests --- .../tests/proxy-deployer.abi.service.spec.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/modules/proxy-deployer/tests/proxy-deployer.abi.service.spec.ts b/src/modules/proxy-deployer/tests/proxy-deployer.abi.service.spec.ts index c309371d8..19dd5c766 100644 --- a/src/modules/proxy-deployer/tests/proxy-deployer.abi.service.spec.ts +++ b/src/modules/proxy-deployer/tests/proxy-deployer.abi.service.spec.ts @@ -94,4 +94,23 @@ describe('Proxy Deployer Abi Service', () => { expect(result).toMatchObject(expectedResult); }); }); + + it('returns built transaction with right arguments including paymentTokens', async () => { + const result = await service.deployMarketplaceSc('erd1dc3yzxxeq69wvf583gw0h67td226gu2ahpk3k50qdgzzym8npltq7ndgha', '10000', ['EGLD']); + + const expectedResult = { + chainID: 'T', + data: 'Y29udHJhY3REZXBsb3lAMDAwMDAwMDAwMDAwMDAwMDA1MDAyZjcwNTEzMzE1ZTIwNDM0MDNhMDkwMTEyNmRkODYzMmNkZTc3MTU5ZTNkZkAyNzEwQDAwMDAwMDA0NDU0NzRjNDQ=', + gasLimit: 70000000, + gasPrice: 1000000000, + nonce: 0, + options: undefined, + receiver: 'erd1qqqqqqqqqqqqqpgqut6lamz9dn480ytj8cmcwvydcu3lj55epltq9t9kam', + sender: 'erd1dc3yzxxeq69wvf583gw0h67td226gu2ahpk3k50qdgzzym8npltq7ndgha', + signature: undefined, + value: '0', + version: 1, + }; + expect(result).toMatchObject(expectedResult); + }); }); From 777a33058ba9cf47734fe756688a732aad8e2948 Mon Sep 17 00:00:00 2001 From: danielailie Date: Wed, 13 Dec 2023 11:49:52 +0200 Subject: [PATCH 06/11] Update schema --- schema.gql | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/schema.gql b/schema.gql index 72287521f..a24b25454 100644 --- a/schema.gql +++ b/schema.gql @@ -207,7 +207,6 @@ input AssetsFilter { """This will work only with an owner address""" collections: [String!] creatorAddress: String - customFilters: CustomFiltersEnum identifier: String identifiers: [String!] likedByAddress: String @@ -686,10 +685,6 @@ input CurrentPaymentTokensFilters { marketplaceKey: String } -enum CustomFiltersEnum { - Tickets -} - input DeployBulkArgs { ownerAddress: String! } @@ -998,9 +993,9 @@ type Mutation { deployBulkSmartContract(input: DeployBulkArgs!): TransactionNode! deployMarketplaceContract(input: DeployMarketplaceArgs!): TransactionNode! deployMinter(input: DeployMinterArgs!): TransactionNode! + deployMinterSmartContract(input: DeployMinterArgsP!): TransactionNode! disableMarketplace(input: UpdateMarketplaceStateArgs!): Boolean! enableMarketplace(input: UpdateMarketplaceStateArgs!): Boolean! - deployMinterSmartContract(input: DeployMinterArgsP!): TransactionNode! endAuction(auctionId: Int!): TransactionNode! flagCollection(input: FlagCollectionInput!): Boolean! flagNft(input: FlagNftInput!): Boolean! @@ -1577,4 +1572,4 @@ input WhitelistMarketplaceArgs { input WhitelistMinterArgs { address: String! adminAddress: String! -} +} \ No newline at end of file From aa5c7169ad7cf3e46d1c75ba19888a3cbb61e081 Mon Sep 17 00:00:00 2001 From: danielailie Date: Wed, 13 Dec 2023 14:48:46 +0200 Subject: [PATCH 07/11] Update deployer requests --- schema.gql | 9 +----- .../minters/minters-mutations.resolver.ts | 2 +- .../minters/models/DeployMinterArgs.ts | 28 ------------------- .../models/requests/DeployMinterRequest.ts | 2 +- .../proxy-deployer/models/DeployMinterArgs.ts | 2 +- .../models/requests/DeployMinterRequest.ts | 4 +-- .../proxy-deployer-mutations.resolver.ts | 24 ++++------------ 7 files changed, 12 insertions(+), 59 deletions(-) delete mode 100644 src/modules/minters/models/DeployMinterArgs.ts diff --git a/schema.gql b/schema.gql index a24b25454..51e715ead 100644 --- a/schema.gql +++ b/schema.gql @@ -706,13 +706,6 @@ input DeployMinterArgs { royaltiesClaimAddress: String! } -input DeployMinterArgsP { - maxNftsPerTransaction: Int! - mintClaimAddress: String! - ownerAddress: String! - royaltiesClaimAddress: String! -} - type ExploreCollectionsStats { activeLast30DaysCount: Int! allCollectionsCount: Int! @@ -993,7 +986,7 @@ type Mutation { deployBulkSmartContract(input: DeployBulkArgs!): TransactionNode! deployMarketplaceContract(input: DeployMarketplaceArgs!): TransactionNode! deployMinter(input: DeployMinterArgs!): TransactionNode! - deployMinterSmartContract(input: DeployMinterArgsP!): TransactionNode! + deployMinterSmartContract(input: DeployMinterArgs!): TransactionNode! disableMarketplace(input: UpdateMarketplaceStateArgs!): Boolean! enableMarketplace(input: UpdateMarketplaceStateArgs!): Boolean! endAuction(auctionId: Int!): TransactionNode! diff --git a/src/modules/minters/minters-mutations.resolver.ts b/src/modules/minters/minters-mutations.resolver.ts index 0b618ffbc..019bd7ec2 100644 --- a/src/modules/minters/minters-mutations.resolver.ts +++ b/src/modules/minters/minters-mutations.resolver.ts @@ -6,7 +6,7 @@ import { JwtOrNativeAuthGuard } from '../auth/jwt.or.native.auth-guard'; import { MintersService } from './minters.service'; import { GqlAdminAuthGuard } from '../auth/gql-admin.auth-guard'; import { WhitelistMinterRequest } from './models/requests/whitelistMinterRequest'; -import { DeployMinterArgs, UpgradeMinterArgs } from './models/DeployMinterArgs'; +import { DeployMinterArgs, UpgradeMinterArgs } from '../proxy-deployer/models/DeployMinterArgs'; import { DeployMinterRequest, UpgradeMinterRequest } from './models/requests/DeployMinterRequest'; import { MintersDeployerAbiService } from './minters-deployer.abi.service'; import { TransactionNode } from '../common/transaction'; diff --git a/src/modules/minters/models/DeployMinterArgs.ts b/src/modules/minters/models/DeployMinterArgs.ts deleted file mode 100644 index f8a7e8749..000000000 --- a/src/modules/minters/models/DeployMinterArgs.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Field, InputType, Int } from '@nestjs/graphql'; -import { Matches } from 'class-validator'; -import { ADDRESS_ERROR, ADDRESS_RGX } from 'src/utils/constants'; - -@InputType() -export class DeployMinterArgs { - @Matches(RegExp(ADDRESS_RGX), { message: ADDRESS_ERROR }) - @Field() - royaltiesClaimAddress: string; - - @Matches(RegExp(ADDRESS_RGX), { message: ADDRESS_ERROR }) - @Field() - ownerAddress: string; - - @Matches(RegExp(ADDRESS_RGX), { message: ADDRESS_ERROR }) - @Field() - mintClaimAddress: string; - - @Field(() => Int) - maxNftsPerTransaction: number; -} - -@InputType() -export class UpgradeMinterArgs { - @Matches(RegExp(ADDRESS_RGX), { message: ADDRESS_ERROR }) - @Field() - minterAddress: string; -} diff --git a/src/modules/minters/models/requests/DeployMinterRequest.ts b/src/modules/minters/models/requests/DeployMinterRequest.ts index bc0367625..80a645f32 100644 --- a/src/modules/minters/models/requests/DeployMinterRequest.ts +++ b/src/modules/minters/models/requests/DeployMinterRequest.ts @@ -1,4 +1,4 @@ -import { DeployMinterArgs, UpgradeMinterArgs } from '../DeployMinterArgs'; +import { DeployMinterArgs, UpgradeMinterArgs } from '../../../proxy-deployer/models/DeployMinterArgs'; export class DeployMinterRequest { royaltiesClaimAddress: string; diff --git a/src/modules/proxy-deployer/models/DeployMinterArgs.ts b/src/modules/proxy-deployer/models/DeployMinterArgs.ts index f223d4771..f8a7e8749 100644 --- a/src/modules/proxy-deployer/models/DeployMinterArgs.ts +++ b/src/modules/proxy-deployer/models/DeployMinterArgs.ts @@ -3,7 +3,7 @@ import { Matches } from 'class-validator'; import { ADDRESS_ERROR, ADDRESS_RGX } from 'src/utils/constants'; @InputType() -export class DeployMinterArgsP { +export class DeployMinterArgs { @Matches(RegExp(ADDRESS_RGX), { message: ADDRESS_ERROR }) @Field() royaltiesClaimAddress: string; diff --git a/src/modules/proxy-deployer/models/requests/DeployMinterRequest.ts b/src/modules/proxy-deployer/models/requests/DeployMinterRequest.ts index 8865dd921..bc0367625 100644 --- a/src/modules/proxy-deployer/models/requests/DeployMinterRequest.ts +++ b/src/modules/proxy-deployer/models/requests/DeployMinterRequest.ts @@ -1,4 +1,4 @@ -import { DeployMinterArgsP, UpgradeMinterArgs } from '../DeployMinterArgs'; +import { DeployMinterArgs, UpgradeMinterArgs } from '../DeployMinterArgs'; export class DeployMinterRequest { royaltiesClaimAddress: string; @@ -9,7 +9,7 @@ export class DeployMinterRequest { Object.assign(this, init); } - static fromArgs(args: DeployMinterArgsP) { + static fromArgs(args: DeployMinterArgs) { return new DeployMinterRequest({ royaltiesClaimAddress: args.royaltiesClaimAddress, mintClaimAddress: args.mintClaimAddress, diff --git a/src/modules/proxy-deployer/proxy-deployer-mutations.resolver.ts b/src/modules/proxy-deployer/proxy-deployer-mutations.resolver.ts index 03210e71b..4cbf7f467 100644 --- a/src/modules/proxy-deployer/proxy-deployer-mutations.resolver.ts +++ b/src/modules/proxy-deployer/proxy-deployer-mutations.resolver.ts @@ -3,13 +3,13 @@ import { BaseResolver } from '../common/base.resolver'; import { UseGuards } from '@nestjs/common'; import { JwtOrNativeAuthGuard } from '../auth/jwt.or.native.auth-guard'; import { GqlAdminAuthGuard } from '../auth/gql-admin.auth-guard'; -import { DeployMinterArgsP, UpgradeMinterArgs } from './models/DeployMinterArgs'; -import { DeployMinterRequest, UpgradeMinterRequest } from './models/requests/DeployMinterRequest'; +import { DeployMinterRequest } from './models/requests/DeployMinterRequest'; import { ProxyDeployerAbiService } from './proxy-deployer.abi.service'; import { TransactionNode } from '../common/transaction'; import { MintersResponse } from './models/MintersResponse'; import { DeployBulkArgs } from './models/DeployBulkArgs'; import { DeployMarketplaceArgs } from './models/DeployMarketplaceArgs'; +import {DeployMinterArgs} from './models/DeployMinterArgs'; @Resolver(() => MintersResponse) export class ProxyDeployerMutationsResolver extends BaseResolver(MintersResponse) { @@ -18,32 +18,20 @@ export class ProxyDeployerMutationsResolver extends BaseResolver(MintersResponse } @Mutation(() => TransactionNode) - // @UseGuards(JwtOrNativeAuthGuard, GqlAdminAuthGuard) - async deployMinterSmartContract(@Args('input') input: DeployMinterArgsP): Promise { + @UseGuards(JwtOrNativeAuthGuard, GqlAdminAuthGuard) + async deployMinterSmartContract(@Args('input') input: DeployMinterArgs): Promise { return await this.minterDeployerService.deployMinterSc(DeployMinterRequest.fromArgs(input)); } @Mutation(() => TransactionNode) - // @UseGuards(JwtOrNativeAuthGuard, GqlAdminAuthGuard) + @UseGuards(JwtOrNativeAuthGuard, GqlAdminAuthGuard) async deployBulkSmartContract(@Args('input') input: DeployBulkArgs): Promise { return await this.minterDeployerService.deployBulkSc(input.ownerAddress); } @Mutation(() => TransactionNode) - // @UseGuards(JwtOrNativeAuthGuard, GqlAdminAuthGuard) + @UseGuards(JwtOrNativeAuthGuard, GqlAdminAuthGuard) async deployMarketplaceContract(@Args('input') input: DeployMarketplaceArgs): Promise { return await this.minterDeployerService.deployBulkSc(input.ownerAddress); } - - // @Mutation(() => TransactionNode) - // @UseGuards(JwtOrNativeAuthGuard, GqlAdminAuthGuard) - // async pauseMinter(@Args('input') input: UpgradeMinterArgs, @AuthUser() user: UserAuthResult): Promise { - // return await this.minterDeployerService.pauseNftMinter(user.address, UpgradeMinterRequest.fromArgs(input)); - // } - - // @Mutation(() => TransactionNode) - // @UseGuards(JwtOrNativeAuthGuard, GqlAdminAuthGuard) - // async resumeMinter(@Args('input') input: UpgradeMinterArgs, @AuthUser() user: UserAuthResult): Promise { - // return await this.minterDeployerService.resumeNftMinter(user.address, UpgradeMinterRequest.fromArgs(input)); - // } } From 7dbe8541ba8a4024b56a394a72052967bdf2accb Mon Sep 17 00:00:00 2001 From: danielailie Date: Wed, 13 Dec 2023 14:54:14 +0200 Subject: [PATCH 08/11] Remove unused services --- .../proxy-deployer-caching.service.ts | 18 ----- .../proxy-deployer/proxy-deployer.module.ts | 6 +- .../proxy-deployer/proxy-deployer.service.ts | 81 ------------------- 3 files changed, 2 insertions(+), 103 deletions(-) delete mode 100644 src/modules/proxy-deployer/proxy-deployer-caching.service.ts delete mode 100644 src/modules/proxy-deployer/proxy-deployer.service.ts diff --git a/src/modules/proxy-deployer/proxy-deployer-caching.service.ts b/src/modules/proxy-deployer/proxy-deployer-caching.service.ts deleted file mode 100644 index f1f7b4cd0..000000000 --- a/src/modules/proxy-deployer/proxy-deployer-caching.service.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import '../../utils/extensions'; -import { RedisCacheService } from '@multiversx/sdk-nestjs-cache'; -import { CacheInfo } from 'src/common/services/caching/entities/cache.info'; -import { MinterEntity } from 'src/db/minters'; - -@Injectable() -export class MintersCachingService { - constructor(private redisCacheService: RedisCacheService) {} - - public async getMinters(getMinters: () => any): Promise { - return await this.redisCacheService.getOrSet(CacheInfo.Minters.key, () => getMinters(), CacheInfo.Minters.ttl); - } - - public async invalidateMinters() { - await this.redisCacheService.delete(CacheInfo.Minters.key); - } -} diff --git a/src/modules/proxy-deployer/proxy-deployer.module.ts b/src/modules/proxy-deployer/proxy-deployer.module.ts index 8df09d89f..0beebfe8a 100644 --- a/src/modules/proxy-deployer/proxy-deployer.module.ts +++ b/src/modules/proxy-deployer/proxy-deployer.module.ts @@ -1,17 +1,15 @@ import { forwardRef, Module } from '@nestjs/common'; import { MxCommunicationModule } from 'src/common'; import { ProxyDeployerMutationsResolver } from './proxy-deployer-mutations.resolver'; -import { MintersService } from './proxy-deployer.service'; import { PubSubListenerModule } from 'src/pubsub/pub.sub.listener.module'; import { CommonModule } from 'src/common.module'; import { AuthModule } from '../auth/auth.module'; -import { MintersCachingService } from './proxy-deployer-caching.service'; import { ProxyDeployerAbiService } from './proxy-deployer.abi.service'; import { CacheEventsPublisherModule } from '../rabbitmq/cache-invalidation/cache-invalidation-publisher/change-events-publisher.module'; @Module({ - providers: [ProxyDeployerMutationsResolver, MintersService, MintersCachingService, ProxyDeployerAbiService], + providers: [ProxyDeployerMutationsResolver, ProxyDeployerAbiService], imports: [PubSubListenerModule, MxCommunicationModule, CommonModule, forwardRef(() => AuthModule), CacheEventsPublisherModule], - exports: [MintersService, MintersCachingService], + exports: [], }) export class ProxyDeployerModuleGraph {} diff --git a/src/modules/proxy-deployer/proxy-deployer.service.ts b/src/modules/proxy-deployer/proxy-deployer.service.ts deleted file mode 100644 index a84a23d3c..000000000 --- a/src/modules/proxy-deployer/proxy-deployer.service.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { Minter } from './models'; -import { PersistenceService } from 'src/common/persistence/persistence.service'; -import { MinterEntity } from 'src/db/minters'; -import { UnableToLoadError } from 'src/common/models/errors/unable-to-load-error'; -import { MintersCachingService } from './proxy-deployer-caching.service'; -import { WhitelistMinterRequest } from './models/requests/whitelistMinterRequest'; -import { MinterFilters } from './models/MinterFilters'; -import { ProxyDeployerAbiService } from './proxy-deployer.abi.service'; -import { CacheEventsPublisherService } from '../rabbitmq/cache-invalidation/cache-invalidation-publisher/change-events-publisher.service'; -import { ChangedEvent, CacheEventTypeEnum } from '../rabbitmq/cache-invalidation/events/changed.event'; - -@Injectable() -export class MintersService { - constructor( - private persistenceService: PersistenceService, - private cacheService: MintersCachingService, - private minterDeployerService: ProxyDeployerAbiService, - private readonly cacheEventsPublisher: CacheEventsPublisherService, - private readonly logger: Logger, - ) {} - - async whitelistMinter(request: WhitelistMinterRequest): Promise { - try { - const contractAddresses = await this.minterDeployerService.getMintersForAddress(request.adminAddress); - if (contractAddresses.includes(request.address)) { - const savedMinter = await this.persistenceService.saveMinter(MinterEntity.fromRequest(request)); - await this.triggerCacheInvalidation(); - return savedMinter ? true : false; - } - return false; - } catch (error) { - this.logger.error('An error has occured while saving the minter ', { - path: this.whitelistMinter.name, - minterAddress: request?.address, - exception: error, - }); - throw new UnableToLoadError(`An error has ocurred while saving the minter: ${request?.address}`); - } - } - - async getMinters(filters?: MinterFilters): Promise { - try { - let minters = await this.cacheService.getMinters(() => this.persistenceService.getMinters()); - if (filters) { - if (filters.minterAddress) minters = minters.filter((m) => m.address === filters.minterAddress); - if (filters.minterAdminAddress) minters = minters.filter((m) => m.adminAddress === filters.minterAdminAddress); - } - - return minters?.map((minter) => Minter.fromEntity(minter)); - } catch (error) { - this.logger.error('An error has occured while getting minters', { - path: this.getMinters.name, - exception: error, - filters, - }); - return []; - } - } - - async getMintersAddresses(): Promise { - try { - const minters = await this.getMinters(); - return minters?.map((x) => x.address); - } catch (error) { - this.logger.error('An error has occured while getting minters addresses', { - path: this.getMintersAddresses.name, - exception: error, - }); - return []; - } - } - - private async triggerCacheInvalidation(): Promise { - await this.cacheEventsPublisher.publish( - new ChangedEvent({ - type: CacheEventTypeEnum.Minters, - }), - ); - } -} From 8f7c1bd69254ff9ec29ac38b1decf580d006ac69 Mon Sep 17 00:00:00 2001 From: danielailie Date: Wed, 13 Dec 2023 14:59:55 +0200 Subject: [PATCH 09/11] Remove unsed models --- .../proxy-deployer/models/AddMinterArgs.ts | 14 ----------- .../proxy-deployer/models/Minter.dto.ts | 24 ------------------- .../proxy-deployer/models/MinterFilters.ts | 18 -------------- .../proxy-deployer/models/MintersResponse.ts | 6 ----- src/modules/proxy-deployer/models/index.ts | 2 -- .../models/requests/whitelistMinterRequest.ts | 16 ------------- .../proxy-deployer-mutations.resolver.ts | 5 ++-- 7 files changed, 2 insertions(+), 83 deletions(-) delete mode 100644 src/modules/proxy-deployer/models/AddMinterArgs.ts delete mode 100644 src/modules/proxy-deployer/models/Minter.dto.ts delete mode 100644 src/modules/proxy-deployer/models/MinterFilters.ts delete mode 100644 src/modules/proxy-deployer/models/MintersResponse.ts delete mode 100644 src/modules/proxy-deployer/models/index.ts delete mode 100644 src/modules/proxy-deployer/models/requests/whitelistMinterRequest.ts diff --git a/src/modules/proxy-deployer/models/AddMinterArgs.ts b/src/modules/proxy-deployer/models/AddMinterArgs.ts deleted file mode 100644 index a060dd3bc..000000000 --- a/src/modules/proxy-deployer/models/AddMinterArgs.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Field, InputType, Int } from '@nestjs/graphql'; -import { Matches } from 'class-validator'; -import { ADDRESS_ERROR, ADDRESS_RGX } from 'src/utils/constants'; - -@InputType() -export class WhitelistMinterArgs { - @Matches(RegExp(ADDRESS_RGX), { message: ADDRESS_ERROR }) - @Field() - address: string; - - @Matches(RegExp(ADDRESS_RGX), { message: ADDRESS_ERROR }) - @Field() - adminAddress: string; -} diff --git a/src/modules/proxy-deployer/models/Minter.dto.ts b/src/modules/proxy-deployer/models/Minter.dto.ts deleted file mode 100644 index 7f15176ab..000000000 --- a/src/modules/proxy-deployer/models/Minter.dto.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Field, ID, ObjectType } from '@nestjs/graphql'; -import { MinterEntity } from 'src/db/minters'; - -@ObjectType() -export class Minter { - @Field(() => ID) - address!: string; - - @Field(() => ID) - adminAddress!: string; - - constructor(init?: Partial) { - Object.assign(this, init); - } - - static fromEntity(minter: MinterEntity) { - return minter - ? new Minter({ - address: minter.address, - adminAddress: minter.adminAddress, - }) - : null; - } -} diff --git a/src/modules/proxy-deployer/models/MinterFilters.ts b/src/modules/proxy-deployer/models/MinterFilters.ts deleted file mode 100644 index d5e7bc000..000000000 --- a/src/modules/proxy-deployer/models/MinterFilters.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Field, InputType, Int } from '@nestjs/graphql'; -import { Matches } from 'class-validator'; -import { ADDRESS_ERROR, ADDRESS_RGX } from 'src/utils/constants'; - -@InputType() -export class MinterFilters { - @Matches(RegExp(ADDRESS_RGX), { message: ADDRESS_ERROR }) - @Field() - minterAddress: string; - - @Matches(RegExp(ADDRESS_RGX), { message: ADDRESS_ERROR }) - @Field() - minterAdminAddress: string; - - constructor(init?: Partial) { - Object.assign(this, init); - } -} diff --git a/src/modules/proxy-deployer/models/MintersResponse.ts b/src/modules/proxy-deployer/models/MintersResponse.ts deleted file mode 100644 index fee79fa0d..000000000 --- a/src/modules/proxy-deployer/models/MintersResponse.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { ObjectType } from '@nestjs/graphql'; -import relayTypes from 'src/modules/common/Relay.types'; -import { Minter } from './Minter.dto'; - -@ObjectType() -export class MintersResponse extends relayTypes(Minter) {} diff --git a/src/modules/proxy-deployer/models/index.ts b/src/modules/proxy-deployer/models/index.ts deleted file mode 100644 index 283d1f663..000000000 --- a/src/modules/proxy-deployer/models/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './Minter.dto'; -export * from './AddMinterArgs'; diff --git a/src/modules/proxy-deployer/models/requests/whitelistMinterRequest.ts b/src/modules/proxy-deployer/models/requests/whitelistMinterRequest.ts deleted file mode 100644 index 1cfc76bd0..000000000 --- a/src/modules/proxy-deployer/models/requests/whitelistMinterRequest.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { WhitelistMinterArgs } from '../AddMinterArgs'; - -export class WhitelistMinterRequest { - address: string; - adminAddress: string; - constructor(init?: Partial) { - Object.assign(this, init); - } - - static fromArgs(args: WhitelistMinterArgs) { - return new WhitelistMinterRequest({ - address: args.address, - adminAddress: args.adminAddress, - }); - } -} diff --git a/src/modules/proxy-deployer/proxy-deployer-mutations.resolver.ts b/src/modules/proxy-deployer/proxy-deployer-mutations.resolver.ts index 4cbf7f467..8e1471974 100644 --- a/src/modules/proxy-deployer/proxy-deployer-mutations.resolver.ts +++ b/src/modules/proxy-deployer/proxy-deployer-mutations.resolver.ts @@ -6,13 +6,12 @@ import { GqlAdminAuthGuard } from '../auth/gql-admin.auth-guard'; import { DeployMinterRequest } from './models/requests/DeployMinterRequest'; import { ProxyDeployerAbiService } from './proxy-deployer.abi.service'; import { TransactionNode } from '../common/transaction'; -import { MintersResponse } from './models/MintersResponse'; import { DeployBulkArgs } from './models/DeployBulkArgs'; import { DeployMarketplaceArgs } from './models/DeployMarketplaceArgs'; import {DeployMinterArgs} from './models/DeployMinterArgs'; -@Resolver(() => MintersResponse) -export class ProxyDeployerMutationsResolver extends BaseResolver(MintersResponse) { +@Resolver(() => TransactionNode) +export class ProxyDeployerMutationsResolver extends BaseResolver(TransactionNode) { constructor(private minterDeployerService: ProxyDeployerAbiService) { super(); } From 262f9ec50657f2eac6d05c8c0bd51a3fce2640a8 Mon Sep 17 00:00:00 2001 From: danielailie Date: Wed, 13 Dec 2023 15:00:57 +0200 Subject: [PATCH 10/11] Remove unused models --- src/modules/proxy-deployer/models/DeployBulkArgs.ts | 7 ------- src/modules/proxy-deployer/models/DeployMarketplaceArgs.ts | 7 ------- 2 files changed, 14 deletions(-) diff --git a/src/modules/proxy-deployer/models/DeployBulkArgs.ts b/src/modules/proxy-deployer/models/DeployBulkArgs.ts index aa520d6ca..5097a04f9 100644 --- a/src/modules/proxy-deployer/models/DeployBulkArgs.ts +++ b/src/modules/proxy-deployer/models/DeployBulkArgs.ts @@ -10,10 +10,3 @@ export class DeployBulkArgs { maxNftsPerTransaction: number; } - -@InputType() -export class UpgradeMinterArgs { - @Matches(RegExp(ADDRESS_RGX), { message: ADDRESS_ERROR }) - @Field() - minterAddress: string; -} diff --git a/src/modules/proxy-deployer/models/DeployMarketplaceArgs.ts b/src/modules/proxy-deployer/models/DeployMarketplaceArgs.ts index 575bbe20f..c4f40db70 100644 --- a/src/modules/proxy-deployer/models/DeployMarketplaceArgs.ts +++ b/src/modules/proxy-deployer/models/DeployMarketplaceArgs.ts @@ -18,10 +18,3 @@ export class DeployMarketplaceArgs { }) paymentTokens: string[]; } - -@InputType() -export class UpgradeMinterArgs { - @Matches(RegExp(ADDRESS_RGX), { message: ADDRESS_ERROR }) - @Field() - minterAddress: string; -} From da2eee5af729d806d2c2cddef80186972789bb86 Mon Sep 17 00:00:00 2001 From: danielailie Date: Wed, 13 Dec 2023 15:31:47 +0200 Subject: [PATCH 11/11] Code formating --- src/modules/auctions/marketplaceUtils.ts | 2 ++ src/modules/proxy-deployer/proxy-deployer-mutations.resolver.ts | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/modules/auctions/marketplaceUtils.ts b/src/modules/auctions/marketplaceUtils.ts index 66956146a..fda65e34f 100644 --- a/src/modules/auctions/marketplaceUtils.ts +++ b/src/modules/auctions/marketplaceUtils.ts @@ -6,7 +6,9 @@ export class MarketplaceUtils { public static readonly xoxnoMarketplaceAbiPath: string = './src/abis/xoxno-nft-marketplace.abi.json'; public static readonly deployerMintersAbiPath: string = './src/abis/nft-minter-deployer.abi.json'; + public static readonly proxyDeployerMintersAbiPath: string = './src/abis/proxy-deployer.abi.json'; + static isExternalMarketplace(type: MarketplaceTypeEnum) { return type === MarketplaceTypeEnum.External; } diff --git a/src/modules/proxy-deployer/proxy-deployer-mutations.resolver.ts b/src/modules/proxy-deployer/proxy-deployer-mutations.resolver.ts index 8e1471974..ed6f44aab 100644 --- a/src/modules/proxy-deployer/proxy-deployer-mutations.resolver.ts +++ b/src/modules/proxy-deployer/proxy-deployer-mutations.resolver.ts @@ -8,7 +8,7 @@ import { ProxyDeployerAbiService } from './proxy-deployer.abi.service'; import { TransactionNode } from '../common/transaction'; import { DeployBulkArgs } from './models/DeployBulkArgs'; import { DeployMarketplaceArgs } from './models/DeployMarketplaceArgs'; -import {DeployMinterArgs} from './models/DeployMinterArgs'; +import { DeployMinterArgs } from './models/DeployMinterArgs'; @Resolver(() => TransactionNode) export class ProxyDeployerMutationsResolver extends BaseResolver(TransactionNode) {