diff --git a/.env.sample b/.env.sample index b7f77968..69c696d0 100644 --- a/.env.sample +++ b/.env.sample @@ -28,3 +28,6 @@ ARGO_HOST=http://localhost:2746/ ARGO_NAMESPACE=argo ARGO_AUTH_TOKEN="Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjZ1QThNV1VqQ1l1S2RRNXdSMlMxWnpqM1dWU0lhRTNZV0lObVJUeXZ6YTAifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJudm0tZGlzYyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhcmdvLXdvcmtmbG93LnNlcnZpY2UtYWNjb3VudC10b2tlbiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJhcmdvLXdvcmtmbG93Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiMmU5ZmJhYTgtNDE1ZS00MDg1LWFhNzktNWY2MTQ0ZmIwZDcwIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Om52bS1kaXNjOmFyZ28td29ya2Zsb3cifQ.SLpDBbEgB0RjIH38xloZjB07N0UBVmswOg5-pQl_K3vqpb15XM5TpWlQpcli5qQKuGGcNttxaxWxDByZ2tjgLFDCDzKle1zDCKz7j0089ZE3mLkDO6hd4Ndb52X8suAWSNdWOCxX0zI3v_JGozEhgnBfxg_pk-aA0hJL7CBnxpPjMD6NuiboaRGwQD4d3Q1mbF6XGRpI_76w3zB8eO3GoIZ-Yrr-8U-5eAhuMuSyMDAX7nr7BF1ci2487q0gFaV2sIY2eVjbnrIxpQKqZ0dg86ZwgwffKeo4RXEYMvB4pJkyEgxhTWyhBbYw_fS-WC5qvXM6r0x_aVll8M0iGe-iWA" NO_GRAPH=true + +JWT_SUBSCRIPTION_SECRET_KEY="12345678901234567890123456789012" +NEVERMINED_PROXY_URI=https://proxy.nevermined.one diff --git a/config/from-env.js b/config/from-env.js index c8722f53..f0e03775 100644 --- a/config/from-env.js +++ b/config/from-env.js @@ -32,6 +32,11 @@ const keys = [ 'ARGO_AUTH_TOKEN', 'COMPUTE_PROVIDER_KEYFILE', 'COMPUTE_PROVIDER_PASSWORD', + + 'JWT_SUBSCRIPTION_SECRET_KEY', + 'NEVERMINED_PROXY_URI', + 'SUBSCRIPTION_DEFAULT_EXPIRY_TIME', + 'NETWORK_AVERAGE_BLOCK_TIME', ] const config = {} diff --git a/package.json b/package.json index 3c702ced..775a2b70 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-ts", - "version": "1.0.0", + "version": "1.1.0", "description": "Nevermined Node", "main": "main.ts", "scripts": { @@ -34,9 +34,9 @@ "@nestjs/swagger": "^5.2.0", "@nestjs/typeorm": "^8.0.3", "@nevermined-io/argo-workflows-api": "^0.1.3", - "@nevermined-io/sdk-dtp": "0.3.0", - "@nevermined-io/sdk": "1.0.0", "@nevermined-io/passport-nevermined": "^0.1.1", + "@nevermined-io/sdk": "1.1.0", + "@nevermined-io/sdk-dtp": "0.4.0", "@sideway/address": "^4.1.3", "@sideway/formula": "^3.0.1", "@sideway/pinpoint": "^2.0.0", @@ -56,7 +56,7 @@ "formdata-polyfill": "^4.0.10", "ipfs-http-client-lite": "^0.3.0", "joi": "^17.6.0", - "jose": "^4.11.2", + "jose": "^4.13.0", "js-yaml": "4.1.0", "jsonwebtoken": "^9.0.0", "lodash": "^4.17.21", @@ -79,7 +79,8 @@ "@commitlint/config-conventional": "^17.4.2", "@faker-js/faker": "^6.0.0-beta.0", "@golevelup/ts-jest": "0.3.4", - "@nestjs/cli": "^8.2.2", + "@nestjs/cli": "^9.2.0", + "@nestjs/schematics": "^9.0.4", "@nestjs/testing": "^8.4.0", "@types/jest": "^29.2.3", "@types/jsonwebtoken": "^8.5.8", diff --git a/src/access/access.controller.ts b/src/access/access.controller.ts index da25c48a..700ba990 100644 --- a/src/access/access.controller.ts +++ b/src/access/access.controller.ts @@ -143,10 +143,11 @@ export class AccessController { nft_amount: BigNumber.from(transferData.nftAmount || '0'), buyer: (req.user || {}).buyer, } - console.log(template, nevermined.assets.servicePlugin[template]) + const plugin = nevermined.assets.servicePlugin[template] const [from] = await nevermined.accounts.list() await plugin.process(params, from, undefined) + return 'success' } diff --git a/src/app.module.ts b/src/app.module.ts index 6e721cbb..ebaab102 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -11,6 +11,7 @@ import { AccessModule } from './access/access.module' import { NeverminedModule } from './shared/nevermined/nvm.module' import { ComputeModule } from './compute/compute.module' import { HttpLoggerMiddleware } from './common/middlewares/http-logger/http-logger.middleware' +import { SubscriptionsModule } from './subscriptions/subscriptions.module' @Module({ imports: [ @@ -23,6 +24,7 @@ import { HttpLoggerMiddleware } from './common/middlewares/http-logger/http-logg AuthModule, NeverminedModule, ComputeModule, + SubscriptionsModule, ], }) export class ApplicationModule { diff --git a/src/routes.ts b/src/routes.ts index 799e317a..67535812 100644 --- a/src/routes.ts +++ b/src/routes.ts @@ -4,12 +4,14 @@ import { EncryptModule } from './encrypt/encrypt.module' import { InfoModule } from './info/info.module' import { AccessModule } from './access/access.module' import { ComputeModule } from './compute/compute.module' +import { SubscriptionsModule } from './subscriptions/subscriptions.module' const exposeCompute: boolean = process.env.ENABLE_COMPUTE === 'true' export const routes: Routes = [ { path: '/api/v1/node/services/encrypt', module: EncryptModule }, { path: '/api/v1/node/services/oauth', module: AuthModule }, + { path: '/api/v1/node/services/subscriptions', module: SubscriptionsModule }, { path: '/api/v1/node/services', module: AccessModule }, { path: '/', module: InfoModule }, ] diff --git a/src/shared/config/config.service.ts b/src/shared/config/config.service.ts index 43bc21bb..0c3b184c 100644 --- a/src/shared/config/config.service.ts +++ b/src/shared/config/config.service.ts @@ -29,6 +29,13 @@ export interface ComputeConfig { compute_provider_password: string } +export interface SubscriptionsConfig { + jwtSecret: Uint8Array + neverminedProxyUri: string + defaultExpiryTime: number + averageBlockTime: number +} + const configProfile = require('../../../config') const DOTENV_SCHEMA = Joi.object({ @@ -37,6 +44,13 @@ const DOTENV_SCHEMA = Joi.object({ .default('development'), JWT_SECRET_KEY: Joi.string().required().error(new Error('JWT_SECRET_KEY is required!')), JWT_EXPIRY_KEY: Joi.string().default('60m'), + JWT_SUBSCRIPTION_SECRET_KEY: Joi.string() + .required() + .error(new Error('JWT_SUBSCRIPTION_SECRET_KEY is required!')), + // defaults to 2 years in seconds + SUBSCRIPTION_DEFAULT_EXPIRY_TIME: Joi.number().default(60 * 60 * 24 * 365 * 2), + // Used to calculate expiry time of subscriptions in milliseconds + NETWORK_AVERAGE_BLOCK_TIME: Joi.number().default(2100), server: Joi.object({ port: Joi.number().default(3000), }), @@ -71,6 +85,7 @@ const DOTENV_SCHEMA = Joi.object({ ARGO_AUTH_TOKEN: Joi.string(), COMPUTE_PROVIDER_KEYFILE: Joi.string(), COMPUTE_PROVIDER_PASSWORD: Joi.string(), + NEVERMINED_PROXY_URI: Joi.string(), }) type DotenvSchemaKeys = @@ -105,11 +120,16 @@ type DotenvSchemaKeys = | 'ARGO_AUTH_TOKEN' | 'COMPUTE_PROVIDER_KEYFILE' | 'COMPUTE_PROVIDER_PASSWORD' + | 'JWT_SUBSCRIPTION_SECRET_KEY' + | 'NEVERMINED_PROXY_URI' + | 'SUBSCRIPTION_DEFAULT_EXPIRY_TIME' + | 'NETWORK_AVERAGE_BLOCK_TIME' export class ConfigService { private readonly envConfig: EnvConfig private readonly crypto: CryptoConfig private readonly compute: ComputeConfig + private readonly subscriptions: SubscriptionsConfig constructor() { this.envConfig = this.validateInput(configProfile) @@ -130,6 +150,17 @@ export class ConfigService { readFileSync(this.get('COMPUTE_PROVIDER_KEYFILE')).toString(), compute_provider_password: this.get('COMPUTE_PROVIDER_PASSWORD'), } + + this.subscriptions = { + jwtSecret: Uint8Array.from( + this.get('JWT_SUBSCRIPTION_SECRET_KEY') + .split('') + .map((x) => parseInt(x)), + ), + neverminedProxyUri: this.get('NEVERMINED_PROXY_URI'), + defaultExpiryTime: this.get('SUBSCRIPTION_DEFAULT_EXPIRY_TIME'), + averageBlockTime: this.get('NETWORK_AVERAGE_BLOCK_TIME'), + } } get(path: DotenvSchemaKeys): T | undefined { @@ -148,6 +179,10 @@ export class ConfigService { return this.compute } + subscriptionsConfig(): SubscriptionsConfig { + return this.subscriptions + } + getProviderBabyjub() { return { x: this.envConfig.PROVIDER_BABYJUB_PUBLIC1 || '', diff --git a/src/shared/nevermined/nvm.service.ts b/src/shared/nevermined/nvm.service.ts index 8c9e57b3..77e05b0a 100644 --- a/src/shared/nevermined/nvm.service.ts +++ b/src/shared/nevermined/nvm.service.ts @@ -87,9 +87,8 @@ export class NeverminedService { const name = file_attributes.name const auth_method = asset.findServiceByType('authorization').service || 'RSAES-OAEP' if (auth_method === 'RSAES-OAEP') { - const filelist = JSON.parse( - await decrypt(this.config.cryptoConfig(), service.attributes.encryptedFiles, 'PSK-RSA'), - ) + const filelist = this.decrypt(service.attributes.encryptedFiles, 'PSK-RSA') + // download url or what? const url: string = filelist[index].url return { url, content_type, dtp: this.isDTP(service.attributes.main), name } @@ -98,6 +97,18 @@ export class NeverminedService { throw new BadRequestException() } + /** + * Decrypts a an encrypted JSON object + * + * @param encryptedJson - The encrypted json object as a string + * @param encryptionMethod - The encryption method used. Currently only PSK-RSA is supported + * + * @returns The decrypted JSON object + */ + async decrypt(encryptedJson: string, encryptionMethod: string): Promise { + return JSON.parse(await decrypt(this.config.cryptoConfig(), encryptedJson, encryptionMethod)) + } + async downloadAsset( did: string, index: number, diff --git a/src/subscriptions/dto/token.dto.ts b/src/subscriptions/dto/token.dto.ts new file mode 100644 index 00000000..259cb86b --- /dev/null +++ b/src/subscriptions/dto/token.dto.ts @@ -0,0 +1,18 @@ +import { ApiProperty } from '@nestjs/swagger' +import { IsString } from 'class-validator' + +export class SubscriptionTokenDto { + @ApiProperty({ + description: 'The Authorization Bearer token', + example: 'eyJhbGciOiJSUzI1NiIsImtpZCI6IjIyIn0.eyJpc3Mi[...omitted for brevity...]', + }) + @IsString() + accessToken: string + + @ApiProperty({ + description: 'The proxy uri that should be used with the provided token', + example: 'https://proxy.nevermined.one', + }) + @IsString() + neverminedProxyUri: string +} diff --git a/src/subscriptions/subscriptions.controller.spec.ts b/src/subscriptions/subscriptions.controller.spec.ts new file mode 100644 index 00000000..73870c2b --- /dev/null +++ b/src/subscriptions/subscriptions.controller.spec.ts @@ -0,0 +1,23 @@ +import { Test, TestingModule } from '@nestjs/testing' +import { ConfigModule } from '../shared/config/config.module' +import { NeverminedModule } from '../shared/nevermined/nvm.module' +import { SubscriptionsController } from './subscriptions.controller' +import { SubscriptionsService } from './subscriptions.service' + +describe('SubscriptionsController', () => { + let controller: SubscriptionsController + + beforeEach(async () => { + const moduleRef: TestingModule = await Test.createTestingModule({ + controllers: [SubscriptionsController], + providers: [SubscriptionsService], + imports: [NeverminedModule, ConfigModule], + }).compile() + + controller = moduleRef.get(SubscriptionsController) + }) + + it('should be defined', () => { + expect(controller).toBeDefined() + }) +}) diff --git a/src/subscriptions/subscriptions.controller.ts b/src/subscriptions/subscriptions.controller.ts new file mode 100644 index 00000000..78b063ba --- /dev/null +++ b/src/subscriptions/subscriptions.controller.ts @@ -0,0 +1,61 @@ +import { Controller, ForbiddenException, Get, Param, Req } from '@nestjs/common' +import { ApiBearerAuth, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' +import { SubscriptionTokenDto } from './dto/token.dto' +import { SubscriptionsService } from './subscriptions.service' + +@ApiTags('Subscriptions') +@Controller() +export class SubscriptionsController { + constructor(private subscriptionService: SubscriptionsService) {} + + @Get(':did') + @ApiOperation({ + description: 'Get and access token for a subscription', + }) + @ApiResponse({ + status: 200, + description: 'Returns the access token', + type: SubscriptionTokenDto, + }) + @ApiResponse({ + status: 401, + description: 'Unauthorized access', + }) + @ApiBearerAuth('Authorization') + async getAccessToken(@Req() req, @Param('did') did: string): Promise { + // get subscription data + const { contractAddress, numberNfts, endpoints, headers } = + await this.subscriptionService.validateDid(did) + + // validate that the subscription is valid + const isValid = await this.subscriptionService.isSubscriptionValid( + contractAddress, + numberNfts, + req.user.address, + ) + + if (!isValid) { + throw new ForbiddenException(`user ${req.user.iss} has not access to subscription ${did}`) + } + + // get expiry time + const expiryTime = await this.subscriptionService.getExpirationTime( + contractAddress, + req.user.address, + ) + + // get access token + const accessToken = await this.subscriptionService.generateToken( + did, + req.user.iss, + endpoints, + expiryTime, + headers, + ) + + return { + accessToken: accessToken, + neverminedProxyUri: this.subscriptionService.neverminedProxyUri, + } + } +} diff --git a/src/subscriptions/subscriptions.module.ts b/src/subscriptions/subscriptions.module.ts new file mode 100644 index 00000000..3718eac0 --- /dev/null +++ b/src/subscriptions/subscriptions.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common' +import { ConfigModule } from '../shared/config/config.module' +import { NeverminedModule } from '../shared/nevermined/nvm.module' +import { SubscriptionsController } from './subscriptions.controller' +import { SubscriptionsService } from './subscriptions.service' + +@Module({ + controllers: [SubscriptionsController], + providers: [SubscriptionsService], + imports: [NeverminedModule, ConfigModule], +}) +export class SubscriptionsModule {} diff --git a/src/subscriptions/subscriptions.service.spec.ts b/src/subscriptions/subscriptions.service.spec.ts new file mode 100644 index 00000000..07367b5b --- /dev/null +++ b/src/subscriptions/subscriptions.service.spec.ts @@ -0,0 +1,21 @@ +import { Test, TestingModule } from '@nestjs/testing' +import { ConfigModule } from '../shared/config/config.module' +import { NeverminedModule } from '../shared/nevermined/nvm.module' +import { SubscriptionsService } from './subscriptions.service' + +describe('SubscriptionsService', () => { + let service: SubscriptionsService + + beforeEach(async () => { + const moduleRef: TestingModule = await Test.createTestingModule({ + providers: [SubscriptionsService], + imports: [NeverminedModule, ConfigModule], + }).compile() + + service = moduleRef.get(SubscriptionsService) + }) + + it('should be defined', () => { + expect(service).toBeDefined() + }) +}) diff --git a/src/subscriptions/subscriptions.service.ts b/src/subscriptions/subscriptions.service.ts new file mode 100644 index 00000000..d668300d --- /dev/null +++ b/src/subscriptions/subscriptions.service.ts @@ -0,0 +1,289 @@ +import { BadRequestException, Injectable } from '@nestjs/common' +import { + DDO, + DDOServiceNotFoundError, + didZeroX, + EventOptions, + findServiceConditionByName, + Service, +} from '@nevermined-io/sdk' +import { NeverminedService } from '../shared/nevermined/nvm.service' +import * as jose from 'jose' +import { ConfigService } from '../shared/config/config.service' + +export interface SubscriptionData { + numberNfts: number + contractAddress: string + endpoints: string[] + headers: { [key: string]: string }[] +} + +@Injectable() +export class SubscriptionsService { + private readonly jwtSecret: Uint8Array + public readonly neverminedProxyUri: string + private readonly defaultExpiryTime: number + private readonly averageBlockTime: number + + constructor(private nvmService: NeverminedService, private config: ConfigService) { + this.jwtSecret = this.config.subscriptionsConfig().jwtSecret + this.neverminedProxyUri = this.config.subscriptionsConfig().neverminedProxyUri + this.defaultExpiryTime = this.config.subscriptionsConfig().defaultExpiryTime + this.averageBlockTime = this.config.subscriptionsConfig().averageBlockTime + } + + /** + * Validates if a DID has an associated subscription + * + * @param did - The DID of the asset with an associated subscription + * + * @throws {@link BadRequestException} + * @returns {@link SubscriptionData} + */ + public async validateDid(did: string): Promise { + // get the DDO + const ddo = await this.nvmService.nevermined.assets.resolve(did) + if (!ddo) { + throw new BadRequestException(`${did} not found.`) + } + + // get the nft-access service + let nftAccessService: Service<'nft-access'> + try { + nftAccessService = ddo.findServiceByType('nft-access') + } catch (e) { + if (e instanceof DDOServiceNotFoundError) { + throw new BadRequestException(`${did} does not contain an 'nft-access' service`) + } else { + throw e + } + } + + // get the nft-holder condition + const nftHolderCondition = findServiceConditionByName(nftAccessService, 'nftHolder') + const numberNfts = Number( + nftHolderCondition.parameters.find((p) => p.name === '_numberNfts').value, + ) + const contractAddress = nftHolderCondition.parameters.find((p) => p.name === '_contractAddress') + .value as string + + // get the web-service endpoints + const metadata = ddo.findServiceByType('metadata') + if (!metadata.attributes.main.webService) { + throw new BadRequestException(`${did} does not contain any web services`) + } + const endpoints = metadata.attributes.main.webService.endpoints.flatMap((e) => Object.values(e)) + + // decrypt the headers + const headers = await this.nvmService.decrypt( + metadata.attributes.main.webService.encryptedAttributes, + 'PSK-RSA', + ) + + return { + numberNfts, + contractAddress, + endpoints, + headers, + } + } + + /** + * Validates if a subscription is valid or not + * + * @param contractAddress - The NFT-721 contract address + * @param numberNfts - Amount of `contractAddress` nfts a user needs to hold in order to get access to the subscription + * @param userAddress - The ethereum address of the user + * + * @returns {@link boolean} + */ + public async isSubscriptionValid( + contractAddress: string, + numberNfts: number, + userAddress: string, + ): Promise { + const nft = await this.nvmService.nevermined.contracts.loadNft721(contractAddress) + const balance = await nft.balanceOf(userAddress) + + return balance.toNumber() >= numberNfts + } + + /** + * Generates a JWT token for a web services subscription + * + * @param did - The did of the web services ddo with an associated subscription + * @param userAddress - The ethereum address of the user requesting the JWT token + * @param endpoints - The web service endpoints provided with the subscription + * @param expiryTime - The expiry time for the JWT token. Set as the time left in the subscription or 2 years for unlimited subscriptions + * @param headers - The headers that should be passed when calling the endpoints + * + * @returns {@link Promise} The base64 encoded JWT Token + */ + public async generateToken( + did: string, + userAddress: string, + endpoints: any, + expiryTime: number, + headers?: any, + ): Promise { + return await new jose.EncryptJWT({ + did: did, + userId: userAddress, + endpoints, + headers, + }) + .setProtectedHeader({ alg: 'dir', enc: 'A128CBC-HS256' }) + .setIssuedAt() + .setExpirationTime(expiryTime) + .encrypt(this.jwtSecret) + } + + /** + * Get the expiration time in seconds for a subscription + * + * @param contractAddress - The NFT-721 contract address of the subscription + * @param userAddress - The address of the user requesting a JWT token + * + * @throws {@link BadRequestException} + * @returns {@link Promise} The expiration time in seconds + */ + public async getExpirationTime(contractAddress: string, userAddress: string): Promise { + // get subscription DDO + const subscriptionDdo = await this.getSubscriptionDdo(contractAddress) + // get duration + const duration = await this.getDuration(subscriptionDdo) + + // if duration is unlimited + if (duration === 0) { + return this.defaultExpiryTime + } + + // get nft transfer block number + const subscriptionTransferBlockNumber = await this.getSubscriptionTransferBlockNumber( + subscriptionDdo.id, + userAddress, + ) + + // get current block number + const currentBlockNumber = await this.nvmService.nevermined.web3.getBlockNumber() + + // blocks left in the subscription + const subscriptionBlocksLeft = subscriptionTransferBlockNumber + duration - currentBlockNumber + if (subscriptionBlocksLeft <= 0) { + throw new BadRequestException( + `Subscription with contract address ${contractAddress} for user ${userAddress} is expired.`, + ) + } + + // calculate the number of seconds left in the subscription + const secondsLeft = Math.floor((subscriptionBlocksLeft * this.averageBlockTime) / 1000) + const currentDate = new Date() + const expiryTime = Math.floor(currentDate.getTime() / 1000) + secondsLeft + + return expiryTime + } + + /** + * Get the subscription DDO + * + * @param contractAddress - The NFT-721 contract address for the subscription + * + * @throws {@link BadRequestException} + * @returns {@link Promise} The DDO for the subscription + */ + private async getSubscriptionDdo(contractAddress: string): Promise { + // retrieve the subscription DDO + const result = await this.nvmService.nevermined.search.bySubscriptionContractAddress( + contractAddress, + ) + const ddo = result.results.pop() + if (!ddo) { + throw new BadRequestException( + `Subscription DDO for contract address ${contractAddress} not found.`, + ) + } + + return ddo + } + + /** + * Get the duration of the subscription in number of blocks + * + * @param subscriptionDDO - The DDO of the subscription + * + * @throws {@link BadRequestException} + * @returns {@link Promise} The duration in number of blocks + */ + private async getDuration(subscriptionDDO: DDO): Promise { + // get the nft-sales service + let nftSalesService: Service<'nft-sales'> + try { + nftSalesService = subscriptionDDO.findServiceByType('nft-sales') + } catch (e) { + if (e instanceof DDOServiceNotFoundError) { + throw new BadRequestException( + `${subscriptionDDO.id} does not contain an 'nft-sales' service`, + ) + } else { + throw e + } + } + + // get the nft-holder condition + const transferNftCondition = findServiceConditionByName(nftSalesService, 'transferNFT') + const duration = Number( + transferNftCondition.parameters.find((p) => p.name === '_duration').value, + ) + + return duration + } + + /** + * Get the block number when a user bought the subscription + * + * @param subscriptionDid - The DID of the asset with associated subscription + * @param userAddress - The address of the user that bough the subscription + * + * @returns {@link Promise} The block number the user bought the subscription + */ + private async getSubscriptionTransferBlockNumber( + subscriptionDid: string, + userAddress: string, + ): Promise { + const eventOptions: EventOptions = { + methodName: 'getFulfilleds', + eventName: 'Fulfilled', + filterSubgraph: { + where: { + _did: didZeroX(subscriptionDid), + _receiver: userAddress, + }, + }, + filterJsonRpc: { + _did: didZeroX(subscriptionDid), + _receiver: userAddress, + }, + result: { + id: true, + _agreementId: true, + _did: true, + _receiver: true, + }, + } + + const [event] = + await this.nvmService.nevermined.keeper.conditions.transferNft721Condition.events.getPastEvents( + eventOptions, + ) + + if (event.blockNumber) { + return event.blockNumber + } else if (event.id) { + const [transactionHash] = event.id.split('-') + const transactionReceipt = await this.nvmService.nevermined.utils.web3.getTransaction( + transactionHash, + ) + return transactionReceipt.blockNumber + } + } +} diff --git a/yarn.lock b/yarn.lock index bd65f1af..60ac556b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10,61 +10,59 @@ "@jridgewell/gen-mapping" "^0.1.0" "@jridgewell/trace-mapping" "^0.3.9" -"@angular-devkit/core@13.3.5": - version "13.3.5" - resolved "https://registry.npmjs.org/@angular-devkit/core/-/core-13.3.5.tgz" - integrity sha512-w7vzK4VoYP9rLgxJ2SwEfrkpKybdD+QgQZlsDBzT0C6Ebp7b4gkNcNVFo8EiZvfDl6Yplw2IAP7g7fs3STn0hQ== +"@angular-devkit/core@15.0.4": + version "15.0.4" + resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-15.0.4.tgz#257ba1d76cd106216d0150f480d0062e726af996" + integrity sha512-4ITpRAevd652SxB+qNesIQ9qfbm7wT5UBU5kJOPPwGL77I21g8CQpkmV1n5VSacPvC9Zbz90feOWexf7w7JzcA== dependencies: - ajv "8.9.0" + ajv "8.11.0" ajv-formats "2.1.1" - fast-json-stable-stringify "2.1.0" - magic-string "0.25.7" + jsonc-parser "3.2.0" rxjs "6.6.7" - source-map "0.7.3" + source-map "0.7.4" -"@angular-devkit/core@13.3.6": - version "13.3.6" - resolved "https://registry.npmjs.org/@angular-devkit/core/-/core-13.3.6.tgz" - integrity sha512-ZmD586B+RnM2CG5+jbXh2NVfIydTc/yKSjppYDDOv4I530YBm6vpfZMwClpiNk6XLbMv7KqX4Tlr4wfxlPYYbA== +"@angular-devkit/core@15.1.4": + version "15.1.4" + resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-15.1.4.tgz#462f123d56f9298cb04b3fa31b425fc31abb76c5" + integrity sha512-PW5MRmd9DHJR4FaXchwQtj9pXnsghSTnwRvfZeCRNYgU2sv0DKyTV+YTSJB+kNXnoPNG1Je6amDEkiXecpspXg== dependencies: - ajv "8.9.0" + ajv "8.12.0" ajv-formats "2.1.1" - fast-json-stable-stringify "2.1.0" - magic-string "0.25.7" + jsonc-parser "3.2.0" rxjs "6.6.7" - source-map "0.7.3" - -"@angular-devkit/schematics-cli@13.3.6": - version "13.3.6" - resolved "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-13.3.6.tgz" - integrity sha512-5tTuu9gbXM0bMk0sin4phmWA3U1Qz53zT/rpEfzQ/+c/s8CoqZ5N1qOnYtemRct3Jxsz1kn4TBpHeriR4r5hHg== - dependencies: - "@angular-devkit/core" "13.3.6" - "@angular-devkit/schematics" "13.3.6" - ansi-colors "4.1.1" - inquirer "8.2.0" - minimist "1.2.6" + source-map "0.7.4" + +"@angular-devkit/schematics-cli@15.1.4": + version "15.1.4" + resolved "https://registry.yarnpkg.com/@angular-devkit/schematics-cli/-/schematics-cli-15.1.4.tgz#f2ea0379e27ddd6b05b302dd88b8d3f1b6c49ec8" + integrity sha512-qkM5Mfs28jZzNcJnSM6RlyrKkYvzhQmWFTxBXnn15k5T4EnSs1gI6O054Xn7jo/senfwNNt7h2Mlz2OmBLo6+w== + dependencies: + "@angular-devkit/core" "15.1.4" + "@angular-devkit/schematics" "15.1.4" + ansi-colors "4.1.3" + inquirer "8.2.4" symbol-observable "4.0.0" + yargs-parser "21.1.1" -"@angular-devkit/schematics@13.3.5": - version "13.3.5" - resolved "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-13.3.5.tgz" - integrity sha512-0N/kL/Vfx0yVAEwa3HYxNx9wYb+G9r1JrLjJQQzDp+z9LtcojNf7j3oey6NXrDUs1WjVZOa/AIdRl3/DuaoG5w== +"@angular-devkit/schematics@15.0.4": + version "15.0.4" + resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-15.0.4.tgz#64de42f9100d7080bc3c59bb06d1e4f6f15a088e" + integrity sha512-/gXiLFS0+xFdx6wPoBpe/c6/K9I5edMpaASqPf4XheKtrsSvL+qTlIi3nsbfItzOiDXbaBmlbxGfkMHz/yg0Ig== dependencies: - "@angular-devkit/core" "13.3.5" - jsonc-parser "3.0.0" - magic-string "0.25.7" + "@angular-devkit/core" "15.0.4" + jsonc-parser "3.2.0" + magic-string "0.26.7" ora "5.4.1" rxjs "6.6.7" -"@angular-devkit/schematics@13.3.6": - version "13.3.6" - resolved "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-13.3.6.tgz" - integrity sha512-yLh5xc92C/FiaAp27coPiKWpSUmwoXF7vMxbJYJTyOXlt0mUITAEAwtrZQNr4yAxW/yvgTdyg7PhXaveQNTUuQ== +"@angular-devkit/schematics@15.1.4": + version "15.1.4" + resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-15.1.4.tgz#30e38777f1bd98e20e6dbe1bfddabc3bcd42605f" + integrity sha512-jpddxo9Qd2yRQ1t9FLhAx5S+luz6HkyhDytq0LFKbxf9ikf1J4oy9riPBFl4pRmrNARWcHZ6GbD20/Ky8PjmXQ== dependencies: - "@angular-devkit/core" "13.3.6" - jsonc-parser "3.0.0" - magic-string "0.25.7" + "@angular-devkit/core" "15.1.4" + jsonc-parser "3.2.0" + magic-string "0.27.0" ora "5.4.1" rxjs "6.6.7" @@ -1206,7 +1204,7 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": +"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.13": version "1.4.14" resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== @@ -1234,32 +1232,32 @@ dependencies: axios "1.1.3" -"@nestjs/cli@^8.2.2": - version "8.2.8" - resolved "https://registry.npmjs.org/@nestjs/cli/-/cli-8.2.8.tgz" - integrity sha512-y5Imcw1EY0OxD3POAM7SLUB1rFdn5FjbfSsyJrokjKmXY+i6KcBdbRrv3Ox7aeJ4W7wXuckIXZEUlK6lC52dnA== +"@nestjs/cli@^9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@nestjs/cli/-/cli-9.2.0.tgz#d174f54d7aaa6695b8e413093e3d18367bc8bec7" + integrity sha512-6B1IjDcJbrOu55oMF67L1x5lDUOZ3Zs9l7bKCBH9D78965m8wq/2rlEWl/gJto5TABLQWy3hVvV/s8VzUlRMxw== dependencies: - "@angular-devkit/core" "13.3.6" - "@angular-devkit/schematics" "13.3.6" - "@angular-devkit/schematics-cli" "13.3.6" - "@nestjs/schematics" "^8.0.3" + "@angular-devkit/core" "15.1.4" + "@angular-devkit/schematics" "15.1.4" + "@angular-devkit/schematics-cli" "15.1.4" + "@nestjs/schematics" "^9.0.0" chalk "3.0.0" chokidar "3.5.3" - cli-table3 "0.6.2" + cli-table3 "0.6.3" commander "4.1.1" - fork-ts-checker-webpack-plugin "7.2.11" + fork-ts-checker-webpack-plugin "7.3.0" inquirer "7.3.3" node-emoji "1.11.0" ora "5.4.1" os-name "4.0.1" - rimraf "3.0.2" + rimraf "4.1.2" shelljs "0.8.5" source-map-support "0.5.21" tree-kill "1.2.2" - tsconfig-paths "3.14.1" - tsconfig-paths-webpack-plugin "3.5.2" - typescript "4.7.4" - webpack "5.73.0" + tsconfig-paths "4.1.2" + tsconfig-paths-webpack-plugin "4.0.0" + typescript "4.9.5" + webpack "5.75.0" webpack-node-externals "3.0.0" "@nestjs/common@^8.4.5": @@ -1314,15 +1312,15 @@ multer "1.4.4-lts.1" tslib "2.4.0" -"@nestjs/schematics@^8.0.3": - version "8.0.11" - resolved "https://registry.npmjs.org/@nestjs/schematics/-/schematics-8.0.11.tgz" - integrity sha512-W/WzaxgH5aE01AiIErE9QrQJ73VR/M/8p8pq0LZmjmNcjZqU5kQyOWUxZg13WYfSpJdOa62t6TZRtFDmgZPoIg== +"@nestjs/schematics@^9.0.0", "@nestjs/schematics@^9.0.4": + version "9.0.4" + resolved "https://registry.yarnpkg.com/@nestjs/schematics/-/schematics-9.0.4.tgz#ab612f5a8e006ca1d617eddc8143ee00b766312b" + integrity sha512-egurCfAc4e5i1r2TmeAF0UrOKejFmT5oTdv4b7HcOVPupc3QGU7CbEfGleL3mkM5AjrixTQeMxU9bJ00ttAbGg== dependencies: - "@angular-devkit/core" "13.3.5" - "@angular-devkit/schematics" "13.3.5" - fs-extra "10.1.0" - jsonc-parser "3.0.0" + "@angular-devkit/core" "15.0.4" + "@angular-devkit/schematics" "15.0.4" + fs-extra "11.1.0" + jsonc-parser "3.2.0" pluralize "8.0.0" "@nestjs/swagger@^5.2.0": @@ -1364,12 +1362,12 @@ jose "^4.11.2" passport-strategy "^1.0.0" -"@nevermined-io/sdk-dtp@0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@nevermined-io/sdk-dtp/-/sdk-dtp-0.3.0.tgz#2cc003bf6ea35b40e1385895a72030fd00ac6402" - integrity sha512-4X6JZCIOTEaEEPlJ9wtQQZ1lZ50nVOQuzH8z/8bdduAIMy05KlMwLJsiu8LlMcPly96d7zkmQR4AQ+P0bUwGEA== +"@nevermined-io/sdk-dtp@0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@nevermined-io/sdk-dtp/-/sdk-dtp-0.4.0.tgz#1e02e89ef335badcbb3864db491e17b449f51e09" + integrity sha512-MMWQ9G7PQQZLrqvkoOttieqLMpvdSIJm+Iv5O/SR0tDAoCMxJMHrF3NtkvVs/13qf4VsmT7KwLqBJ6/MQdot3A== dependencies: - "@nevermined-io/sdk" "1.0.0" + "@nevermined-io/sdk" "1.1.0" circomlibjs "^0.1.1" eciesjs "^0.3.15" ffjavascript "^0.2.55" @@ -1377,10 +1375,10 @@ snarkjs "^0.4.26" web3-utils "^1.7.4" -"@nevermined-io/sdk@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@nevermined-io/sdk/-/sdk-1.0.0.tgz#fa1ceb831e842f0387f504a0561137b3a0a61eb5" - integrity sha512-vaqx1WXRafjXpW4OcyBExR+Fl9QNE7B+5JLyCzTjuFKY35MmaTbwRgfw8r1JiSOiQgXiBVqrXMKi4+QsKL5IYg== +"@nevermined-io/sdk@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@nevermined-io/sdk/-/sdk-1.1.0.tgz#b18d63b2c17ef0508aed363a24750bbcfd1b8e87" + integrity sha512-UTT1l9VCIHVs7GM/PKnRFUHjT6KQIwH9WZ5fPQEQpeKzP4nDEmsyMOse9q2I4YtPY4O6az41EHWvfFmmljxhLw== dependencies: "@nevermined-io/subgraphs" "0.5.0" assert "^2.0.0" @@ -1464,7 +1462,6 @@ resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f" integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg== - "@sideway/pinpoint@^2.0.0": version "2.0.0" resolved "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz" @@ -2137,6 +2134,11 @@ acorn@^8.4.1, acorn@^8.5.0, acorn@^8.8.0: resolved "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz" integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA== +acorn@^8.7.1: + version "8.8.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" + integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== + aes-js@3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz" @@ -2162,10 +2164,20 @@ ajv-keywords@^3.5.2: resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv@8.9.0: - version "8.9.0" - resolved "https://registry.npmjs.org/ajv/-/ajv-8.9.0.tgz" - integrity sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ== +ajv@8.11.0: + version "8.11.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.0.tgz#977e91dd96ca669f54a11e23e378e33b884a565f" + integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +ajv@8.12.0, ajv@^8.11.0: + version "8.12.0" + resolved "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz" + integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== dependencies: fast-deep-equal "^3.1.1" json-schema-traverse "^1.0.0" @@ -2192,20 +2204,10 @@ ajv@^8.0.0: require-from-string "^2.0.2" uri-js "^4.2.2" -ajv@^8.11.0: - version "8.12.0" - resolved "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz" - integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== - dependencies: - fast-deep-equal "^3.1.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - uri-js "^4.2.2" - -ansi-colors@4.1.1: - version "4.1.1" - resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz" - integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== +ansi-colors@4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: version "4.3.2" @@ -3065,10 +3067,10 @@ cli-spinners@^2.5.0: resolved "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz" integrity sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw== -cli-table3@0.6.2: - version "0.6.2" - resolved "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.2.tgz" - integrity sha512-QyavHCaIC80cMivimWu4aWHilIpiDpfm3hGmqAmXVL1UsnbLuBSMd21hTX6VY4ZSDSM73ESLeF8TOYId3rBTbw== +cli-table3@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.3.tgz#61ab765aac156b52f222954ffc607a6f01dbeeb2" + integrity sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg== dependencies: string-width "^4.2.0" optionalDependencies: @@ -3691,7 +3693,7 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enhanced-resolve@^5.7.0, enhanced-resolve@^5.9.3: +enhanced-resolve@^5.10.0, enhanced-resolve@^5.7.0: version "5.12.0" resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz" integrity sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ== @@ -4336,7 +4338,7 @@ fast-glob@^3.2.9: merge2 "^1.3.0" micromatch "^4.0.4" -fast-json-stable-stringify@2.1.0, fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: +fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== @@ -4491,10 +4493,10 @@ for-each@^0.3.3: dependencies: is-callable "^1.1.3" -fork-ts-checker-webpack-plugin@7.2.11: - version "7.2.11" - resolved "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-7.2.11.tgz" - integrity sha512-2e5+NyTUTE1Xq4fWo7KFEQblCaIvvINQwUX3jRmEGlgCTc1Ecqw/975EfQrQ0GEraxJTnp8KB9d/c8hlCHUMJA== +fork-ts-checker-webpack-plugin@7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-7.3.0.tgz#a9c984a018493962360d7c7e77a67b44a2d5f3aa" + integrity sha512-IN+XTzusCjR5VgntYFgxbxVx3WraPRnKehBFrf00cMSrtUuW9MsG9dhL6MWpY6MkjC3wVwoujfCDgZZCQwbswA== dependencies: "@babel/code-frame" "^7.16.7" chalk "^4.1.2" @@ -4504,6 +4506,7 @@ fork-ts-checker-webpack-plugin@7.2.11: fs-extra "^10.0.0" memfs "^3.4.1" minimatch "^3.0.4" + node-abort-controller "^3.0.1" schema-utils "^3.1.1" semver "^7.3.5" tapable "^2.2.1" @@ -4562,19 +4565,19 @@ fresh@0.5.2: resolved "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== -fs-extra@10.1.0, fs-extra@^10.0.0: - version "10.1.0" - resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz" - integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== +fs-extra@11.1.0, fs-extra@^11.0.0: + version "11.1.0" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.0.tgz" + integrity sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw== dependencies: graceful-fs "^4.2.0" jsonfile "^6.0.1" universalify "^2.0.0" -fs-extra@^11.0.0: - version "11.1.0" - resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.0.tgz" - integrity sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw== +fs-extra@^10.0.0: + version "10.1.0" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== dependencies: graceful-fs "^4.2.0" jsonfile "^6.0.1" @@ -5016,10 +5019,10 @@ inquirer@7.3.3: strip-ansi "^6.0.0" through "^2.3.6" -inquirer@8.2.0: - version "8.2.0" - resolved "https://registry.npmjs.org/inquirer/-/inquirer-8.2.0.tgz" - integrity sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ== +inquirer@8.2.4: + version "8.2.4" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.4.tgz#ddbfe86ca2f67649a67daa6f1051c128f684f0b4" + integrity sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg== dependencies: ansi-escapes "^4.2.1" chalk "^4.1.1" @@ -5031,10 +5034,11 @@ inquirer@8.2.0: mute-stream "0.0.8" ora "^5.4.1" run-async "^2.4.0" - rxjs "^7.2.0" + rxjs "^7.5.5" string-width "^4.1.0" strip-ansi "^6.0.0" through "^2.3.6" + wrap-ansi "^7.0.0" internal-slot@^1.0.3: version "1.0.3" @@ -5778,6 +5782,11 @@ jose@^4.11.2: resolved "https://registry.npmjs.org/jose/-/jose-4.11.2.tgz" integrity sha512-njj0VL2TsIxCtgzhO+9RRobBvws4oYyCM8TpvoUQwl/MbIM3NFJRR9+e6x0sS5xXaP1t6OCBkaBME98OV9zU5A== +jose@^4.13.0: + version "4.13.0" + resolved "https://registry.yarnpkg.com/jose/-/jose-4.13.0.tgz#bee9096c666301641d360577572a3834c3842dfc" + integrity sha512-v6BN7fuPVfG9XIxcPT2jzyAg5EmA/mtNeJEXJ7d31Wz7fFOqOZeN8mPtNJYQmnuAIxJII7EcURcbZ7qXs9a4kA== + jose@^4.5.1: version "4.11.1" resolved "https://registry.npmjs.org/jose/-/jose-4.11.1.tgz" @@ -5860,10 +5869,15 @@ json5@^1.0.1: dependencies: minimist "^1.2.0" -jsonc-parser@3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz" - integrity sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA== +json5@^2.2.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +jsonc-parser@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" + integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w== jsonfile@^6.0.1: version "6.1.0" @@ -5874,8 +5888,12 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" +jsonparse@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" + integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== -jsonwebtoken@8.5.1, jsonwebtoken@^8.5.1: +jsonwebtoken@8.5.1: version "8.5.1" resolved "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz" integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w== @@ -6196,12 +6214,19 @@ macos-release@^2.5.0: resolved "https://registry.npmjs.org/macos-release/-/macos-release-2.5.0.tgz" integrity sha512-EIgv+QZ9r+814gjJj0Bt5vSLJLzswGmSUbUpbi9AIr/fsN2IWFBl2NucV9PAiek+U1STK468tEkxmVYUtuAN3g== -magic-string@0.25.7: - version "0.25.7" - resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz" - integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== +magic-string@0.26.7: + version "0.26.7" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.26.7.tgz#caf7daf61b34e9982f8228c4527474dac8981d6f" + integrity sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow== + dependencies: + sourcemap-codec "^1.4.8" + +magic-string@0.27.0: + version "0.27.0" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.27.0.tgz#e4a3413b4bab6d98d2becffd48b4a257effdbbf3" + integrity sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA== dependencies: - sourcemap-codec "^1.4.4" + "@jridgewell/sourcemap-codec" "^1.4.13" make-dir@^3.0.0: version "3.1.0" @@ -6390,11 +6415,6 @@ minimist-options@4.1.0: is-plain-obj "^1.1.0" kind-of "^6.0.3" -minimist@1.2.6: - version "1.2.6" - resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz" - integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== - minimist@^1.2.0, minimist@^1.2.6: version "1.2.7" resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz" @@ -6536,6 +6556,11 @@ nise@^5.1.2: just-extend "^4.0.2" path-to-regexp "^1.7.0" +node-abort-controller@^3.0.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-3.1.1.tgz#a94377e964a9a37ac3976d848cb5c765833b8548" + integrity sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ== + node-addon-api@^2.0.0: version "2.0.2" resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz" @@ -7356,12 +7381,10 @@ rfdc@^1.3.0: resolved "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz" integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== -rimraf@3.0.2, rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" +rimraf@4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-4.1.2.tgz#20dfbc98083bdfaa28b01183162885ef213dbf7c" + integrity sha512-BlIbgFryTbw3Dz6hyoWFhKk+unCcHMSkZGrTFVAx2WmttdBSonsdtRlwiuTbDqTKr+UlXIUqJVS4QT5tUzGENQ== rimraf@^2.6.1: version "2.7.1" @@ -7370,6 +7393,13 @@ rimraf@^2.6.1: dependencies: glob "^7.1.3" +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz" @@ -7404,20 +7434,20 @@ rxjs@6.6.7, rxjs@^6.6.0: dependencies: tslib "^1.9.0" -rxjs@^7.2.0, rxjs@^7.5.7: - version "7.5.7" - resolved "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz" - integrity sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA== - dependencies: - tslib "^2.1.0" - -rxjs@^7.8.0: +rxjs@^7.5.5, rxjs@^7.8.0: version "7.8.0" resolved "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz" integrity sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg== dependencies: tslib "^2.1.0" +rxjs@^7.5.7: + version "7.5.7" + resolved "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz" + integrity sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA== + dependencies: + tslib "^2.1.0" + safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" @@ -7683,19 +7713,19 @@ source-map-support@0.5.21, source-map-support@^0.5.12, source-map-support@~0.5.2 buffer-from "^1.0.0" source-map "^0.6.0" -source-map@0.7.3: - version "0.7.3" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz" - integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== +source-map@0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" + integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== source-map@^0.6.0, source-map@^0.6.1: version "0.6.1" resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -sourcemap-codec@^1.4.4: +sourcemap-codec@^1.4.8: version "1.4.8" - resolved "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz" + resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== spdx-correct@^3.0.0: @@ -8165,16 +8195,25 @@ ts-node@^10.4.0, ts-node@^10.8.1: v8-compile-cache-lib "^3.0.1" yn "3.1.1" -tsconfig-paths-webpack-plugin@3.5.2: - version "3.5.2" - resolved "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-3.5.2.tgz" - integrity sha512-EhnfjHbzm5IYI9YPNVIxx1moxMI4bpHD2e0zTXeDNQcwjjRaGepP7IhTHJkyDBG0CAOoxRfe7jCG630Ou+C6Pw== +tsconfig-paths-webpack-plugin@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.0.0.tgz#84008fc3e3e0658fdb0262758b07b4da6265ff1a" + integrity sha512-fw/7265mIWukrSHd0i+wSwx64kYUSAKPfxRDksjKIYTxSAp9W9/xcZVBF4Kl0eqQd5eBpAQ/oQrc5RyM/0c1GQ== dependencies: chalk "^4.1.0" enhanced-resolve "^5.7.0" - tsconfig-paths "^3.9.0" + tsconfig-paths "^4.0.0" + +tsconfig-paths@4.1.2, tsconfig-paths@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.1.2.tgz#4819f861eef82e6da52fb4af1e8c930a39ed979a" + integrity sha512-uhxiMgnXQp1IR622dUXI+9Ehnws7i/y6xvpZB9IbUVOPy0muvdvgXeZOn88UcGPiT98Vp3rJPTa8bFoalZ3Qhw== + dependencies: + json5 "^2.2.2" + minimist "^1.2.6" + strip-bom "^3.0.0" -tsconfig-paths@3.14.1, tsconfig-paths@^3.13.0, tsconfig-paths@^3.14.1, tsconfig-paths@^3.9.0: +tsconfig-paths@^3.13.0, tsconfig-paths@^3.14.1: version "3.14.1" resolved "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz" integrity sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ== @@ -8323,16 +8362,16 @@ typedarray@^0.0.6: resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== -typescript@4.7.4: - version "4.7.4" - resolved "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz" - integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ== - typescript@4.8.2: version "4.8.2" resolved "https://registry.npmjs.org/typescript/-/typescript-4.8.2.tgz" integrity sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw== +typescript@4.9.5: + version "4.9.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" + integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== + typescript@^4.6.4, typescript@^4.7.3: version "4.9.3" resolved "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz" @@ -8501,9 +8540,9 @@ wasmcurves@0.2.0: dependencies: wasmbuilder "0.0.16" -watchpack@^2.3.1: +watchpack@^2.4.0: version "2.4.0" - resolved "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== dependencies: glob-to-regexp "^0.4.1" @@ -8559,21 +8598,21 @@ webpack-sources@^3.2.3: resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz" integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== -webpack@5.73.0: - version "5.73.0" - resolved "https://registry.npmjs.org/webpack/-/webpack-5.73.0.tgz" - integrity sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA== +webpack@5.75.0: + version "5.75.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.75.0.tgz#1e440468647b2505860e94c9ff3e44d5b582c152" + integrity sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ== dependencies: "@types/eslint-scope" "^3.7.3" "@types/estree" "^0.0.51" "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/wasm-edit" "1.11.1" "@webassemblyjs/wasm-parser" "1.11.1" - acorn "^8.4.1" + acorn "^8.7.1" acorn-import-assertions "^1.7.6" browserslist "^4.14.5" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.9.3" + enhanced-resolve "^5.10.0" es-module-lexer "^0.9.0" eslint-scope "5.1.1" events "^3.2.0" @@ -8586,7 +8625,7 @@ webpack@5.73.0: schema-utils "^3.1.0" tapable "^2.1.1" terser-webpack-plugin "^5.1.3" - watchpack "^2.3.1" + watchpack "^2.4.0" webpack-sources "^3.2.3" whatwg-url@^5.0.0: @@ -8729,16 +8768,16 @@ yaml@^2.1.3: resolved "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz" integrity sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw== +yargs-parser@21.1.1, yargs-parser@^21.0.1, yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + yargs-parser@^20.2.3: version "20.2.9" resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== -yargs-parser@^21.0.1, yargs-parser@^21.1.1: - version "21.1.1" - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz" - integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== - yargs@^17.0.0, yargs@^17.3.1: version "17.6.2" resolved "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz"