diff --git a/backend/package.json b/backend/package.json index 2e22306c..81e34710 100644 --- a/backend/package.json +++ b/backend/package.json @@ -42,7 +42,9 @@ "@sentry/profiling-node": "^8.17.0", "@types/ws": "^8.5.11", "axios": "^1.7.2", - "cache-manager": "^5.7.1", + "cache-manager": "^5.2.3", + "cache-manager-redis-yet": "^4.1.2", + "redis": "^4.6.7", "dataloader": "^2.2.2", "fastify": "^4.28.1", "graphql": "^16.9.0", diff --git a/backend/src/app.module.ts b/backend/src/app.module.ts index 8677e8c6..bd6d07ac 100644 --- a/backend/src/app.module.ts +++ b/backend/src/app.module.ts @@ -1,10 +1,12 @@ import { APP_INTERCEPTOR } from '@nestjs/core'; -import { CacheModule } from '@nestjs/cache-manager'; +import { CacheModule, CacheStore } from '@nestjs/cache-manager'; import { HttpException, Module } from '@nestjs/common'; import { ConfigModule, ConfigService } from '@nestjs/config'; import { SentryInterceptor, SentryModule } from '@ntegral/nestjs-sentry'; import { nodeProfilingIntegration } from '@sentry/profiling-node'; -import { envSchema } from './env'; +import type { RedisClientOptions } from 'redis'; +import { redisStore } from 'cache-manager-redis-yet'; +import { Env, envSchema } from './env'; import { CoreModule } from './core/core.module'; import { ApiModule } from './modules/api.module'; @@ -20,7 +22,7 @@ import { ApiModule } from './modules/api.module'; }), SentryModule.forRootAsync({ imports: [ConfigModule], - useFactory: async (configService: ConfigService) => ({ + useFactory: async (configService: ConfigService) => ({ dsn: configService.get('SENTRY_DSN'), environment: configService.get('NODE_ENV'), tracesSampleRate: 0.1, @@ -33,8 +35,18 @@ import { ApiModule } from './modules/api.module'; }), inject: [ConfigService], }), - CacheModule.register({ + CacheModule.registerAsync({ isGlobal: true, + imports: [ConfigModule], + useFactory: async (configService: ConfigService) => { + const store = await redisStore({ + url: configService.get('REDIS_URL'), + }) as unknown as CacheStore; + return { + store, + }; + }, + inject: [ConfigService], }), CoreModule, ApiModule, diff --git a/backend/src/env.ts b/backend/src/env.ts index 42626ee4..fa2104c0 100644 --- a/backend/src/env.ts +++ b/backend/src/env.ts @@ -3,6 +3,7 @@ import { NetworkType } from './constants'; export const envSchema = z .object({ + NODE_ENV: z.enum(['development', 'production', 'test']).default('development'), NETWORK: z.enum([NetworkType.mainnet, NetworkType.testnet]).default(NetworkType.testnet), ENABLED_GRAPHQL_PLAYGROUND: z.boolean().default(true), @@ -13,6 +14,8 @@ export const envSchema = z CKB_EXPLORER_API_URL: z.string(), CKB_RPC_WEBSOCKET_URL: z.string(), + + SENTRY_DSN: z.string().optional(), }) .and( z.union([ diff --git a/backend/src/modules/bitcoin/bitcoin.resolver.ts b/backend/src/modules/bitcoin/bitcoin.resolver.ts index a0c9610d..3e5f988b 100644 --- a/backend/src/modules/bitcoin/bitcoin.resolver.ts +++ b/backend/src/modules/bitcoin/bitcoin.resolver.ts @@ -2,10 +2,7 @@ import { Float, Parent, Query, ResolveField, Resolver } from '@nestjs/graphql'; import { BitcoinApiService } from 'src/core/bitcoin-api/bitcoin-api.service'; import { BitcoinBaseChainInfo, BitcoinChainInfo, BitcoinFees } from './bitcoin.model'; import { Loader } from '@applifting-io/nestjs-dataloader'; -import { - BitcoinBlockTransactionsLoader, - BitcoinBlockTransactionsLoaderType, -} from './block/block.dataloader'; +import { BitcoinBlockTxidsLoader, BitcoinBlockTxidsLoaderType } from './block/dataloader/block-txids.loader'; // 60 * 24 = 1440 minutes const BLOCK_NUMBER_OF_24_HOURS = 144; @@ -23,16 +20,16 @@ export class BitcoinResolver { @ResolveField(() => Float) public async transactionsCountIn24Hours( @Parent() chainInfo: BitcoinBaseChainInfo, - @Loader(BitcoinBlockTransactionsLoader) blockTxsLoader: BitcoinBlockTransactionsLoaderType, + @Loader(BitcoinBlockTxidsLoader) blockTxidsLoader: BitcoinBlockTxidsLoaderType, ): Promise { const blockNumbers = Array.from( { length: BLOCK_NUMBER_OF_24_HOURS }, (_, i) => chainInfo.tipBlockHeight - i, ); - const transactions = await blockTxsLoader.loadMany( + const txidsCollection = await blockTxidsLoader.loadMany( blockNumbers.map((blockNumber) => ({ height: blockNumber })), ); - const count = transactions + const count = txidsCollection .map((txs) => (txs instanceof Array ? txs : [])) .reduce((acc, txs) => acc + txs?.length ?? 0, 0); return count; diff --git a/backend/src/modules/bitcoin/block/block.dataloader.ts b/backend/src/modules/bitcoin/block/block.dataloader.ts deleted file mode 100644 index bf0928e3..00000000 --- a/backend/src/modules/bitcoin/block/block.dataloader.ts +++ /dev/null @@ -1,72 +0,0 @@ -import DataLoader from 'dataloader'; -import { Injectable, Logger } from '@nestjs/common'; -import { NestDataLoader } from '@applifting-io/nestjs-dataloader'; -import { DataLoaderResponse } from 'src/common/type/dataloader'; -import { BitcoinApiService } from 'src/core/bitcoin-api/bitcoin-api.service'; -import * as BitcoinApi from 'src/core/bitcoin-api/bitcoin-api.schema'; - -@Injectable() -export class BitcoinBlockLoader implements NestDataLoader { - private logger = new Logger(BitcoinBlockLoader.name); - - constructor(private bitcoinApiService: BitcoinApiService) { } - - public getBatchFunction() { - return async (keys: string[]) => { - this.logger.debug(`Loading bitcoin blocks: ${keys.join(', ')}`); - const results = await Promise.allSettled( - keys.map(async (key) => { - let hash = key; - if (!hash.startsWith('0')) { - hash = await this.bitcoinApiService.getBlockHeight({ height: parseInt(key, 10) }); - } - const block = await this.bitcoinApiService.getBlock({ hash }); - return block; - }), - ); - return results.map((result) => (result.status === 'fulfilled' ? result.value : null)); - }; - } -} -export type BitcoinBlockLoaderType = DataLoader; -export type BitcoinBlockLoaderResponse = DataLoaderResponse; - -export interface BitcoinBlockTransactionsLoaderParams { - hash?: string; - height?: number; - startIndex?: number; -} - -@Injectable() -export class BitcoinBlockTransactionsLoader - implements NestDataLoader { - private logger = new Logger(BitcoinBlockLoader.name); - - constructor(private bitcoinApiService: BitcoinApiService) { } - - public getBatchFunction() { - return async (batchProps: BitcoinBlockTransactionsLoaderParams[]) => { - this.logger.debug(`Loading bitcoin block transactions: ${batchProps}`); - const results = await Promise.allSettled( - batchProps.map(async (props) => { - let hash = props.hash; - if (props.height && !hash) { - hash = await this.bitcoinApiService.getBlockHeight({ height: props.height }); - } - const txs = await this.bitcoinApiService.getBlockTxs({ - hash, - startIndex: props.startIndex, - }); - return txs; - }), - ); - return results.map((result) => (result.status === 'fulfilled' ? result.value : null)); - }; - } -} -export type BitcoinBlockTransactionsLoaderType = DataLoader< - BitcoinBlockTransactionsLoaderParams, - BitcoinApi.Transaction[] | null ->; -export type BitcoinBlockTransactionsLoaderResponse = - DataLoaderResponse; diff --git a/backend/src/modules/bitcoin/block/block.module.ts b/backend/src/modules/bitcoin/block/block.module.ts index c0a13740..f68533d8 100644 --- a/backend/src/modules/bitcoin/block/block.module.ts +++ b/backend/src/modules/bitcoin/block/block.module.ts @@ -1,11 +1,18 @@ import { Module } from '@nestjs/common'; import { BitcoinApiModule } from 'src/core/bitcoin-api/bitcoin-api.module'; -import { BitcoinBlockLoader, BitcoinBlockTransactionsLoader } from './block.dataloader'; import { BitcoinBlockResolver } from './block.resolver'; +import { BitcoinBlockLoader } from './dataloader/block.loader'; +import { BitcoinBlockTransactionsLoader } from './dataloader/block-transactions.loader'; +import { BitcoinBlockTxidsLoader } from './dataloader/block-txids.loader'; @Module({ imports: [BitcoinApiModule], - providers: [BitcoinBlockResolver, BitcoinBlockLoader, BitcoinBlockTransactionsLoader], - exports: [BitcoinBlockLoader, BitcoinBlockTransactionsLoader], + providers: [ + BitcoinBlockResolver, + BitcoinBlockLoader, + BitcoinBlockTransactionsLoader, + BitcoinBlockTxidsLoader, + ], + exports: [BitcoinBlockLoader, BitcoinBlockTransactionsLoader, BitcoinBlockTxidsLoader], }) export class BitcoinBlockModule {} diff --git a/backend/src/modules/bitcoin/block/block.resolver.ts b/backend/src/modules/bitcoin/block/block.resolver.ts index 919edf8e..fad11154 100644 --- a/backend/src/modules/bitcoin/block/block.resolver.ts +++ b/backend/src/modules/bitcoin/block/block.resolver.ts @@ -4,12 +4,8 @@ import { Args, Float, Parent, Query, ResolveField, Resolver } from '@nestjs/grap import { BitcoinBaseTransaction, BitcoinTransaction } from '../transaction/transaction.model'; import { BitcoinAddress, BitcoinBaseAddress } from '../address/address.model'; import { BitcoinBaseBlock, BitcoinBlock, FeeRateRange } from './block.model'; -import { - BitcoinBlockLoader, - BitcoinBlockLoaderType, - BitcoinBlockTransactionsLoader, - BitcoinBlockTransactionsLoaderType, -} from './block.dataloader'; +import { BitcoinBlockLoader, BitcoinBlockLoaderType } from './dataloader/block.loader'; +import { BitcoinBlockTransactionsLoader, BitcoinBlockTransactionsLoaderType } from './dataloader/block-transactions.loader'; @Resolver(() => BitcoinBlock) export class BitcoinBlockResolver { diff --git a/backend/src/modules/bitcoin/block/dataloader/base.ts b/backend/src/modules/bitcoin/block/dataloader/base.ts new file mode 100644 index 00000000..ee359790 --- /dev/null +++ b/backend/src/modules/bitcoin/block/dataloader/base.ts @@ -0,0 +1,94 @@ +import { Logger } from '@nestjs/common'; +import { BitcoinApiService } from 'src/core/bitcoin-api/bitcoin-api.service'; +import * as BitcoinApi from 'src/core/bitcoin-api/bitcoin-api.schema'; +import { Cache } from '@nestjs/cache-manager'; + +export abstract class BitcoinBaseLoader { + protected logger = new Logger(BitcoinBaseLoader.name); + abstract bitcoinApiService: BitcoinApiService; + abstract cacheManager: Cache; + + private async getBlockHashByHeight(height: number): Promise { + const cacheKey = `bitcoinApiService#getBlockHeight:${height}`; + const cached = await this.cacheManager.get(cacheKey); + if (cached) { + return cached; + } + const hash = await this.bitcoinApiService.getBlockHeight({ height }); + await this.cacheManager.set(cacheKey, hash); + return hash; + } + + private async getBlockByHash(hash: string): Promise { + const cacheKey = `bitcoinApiService#getBlock:${hash}`; + const cached = await this.cacheManager.get(cacheKey); + if (cached) { + return cached; + } + const block = await this.bitcoinApiService.getBlock({ hash }); + const ttl = Date.now() - block.timestamp * 1000; + await this.cacheManager.set(cacheKey, block, ttl); + return block; + } + + private async getBlockTxsByHash( + hash: string, + startIndex: number, + ): Promise { + const cacheKey = `bitcoinApiService#getBlockTxs:${hash}:${startIndex}`; + const cached = await this.cacheManager.get(cacheKey); + if (cached) { + return cached; + } + const txs = await this.bitcoinApiService.getBlockTxs({ hash, startIndex }); + await this.cacheManager.set(cacheKey, txs); + return txs; + } + + private async getBlockTxidsByHash(hash: string): Promise { + const cacheKey = `bitcoinApiService#getBlockTxids:${hash}`; + const cached = await this.cacheManager.get(cacheKey); + if (cached) { + return cached; + } + const txids = await this.bitcoinApiService.getBlockTxids({ hash }); + await this.cacheManager.set(cacheKey, txids); + return txids; + } + + protected async getBlock(hashOrHeight: string): Promise { + if (hashOrHeight.startsWith('0')) { + const block = await this.getBlockByHash(hashOrHeight); + return block; + } + const height = parseInt(hashOrHeight, 10); + const hash = await this.getBlockHashByHeight(height); + const block = await this.getBlockByHash(hash); + return block; + } + + protected async getBlockTxs( + hashOrHeight: string, + startIndex: number, + ): Promise { + if (hashOrHeight.startsWith('0')) { + return this.getBlockTxsByHash(hashOrHeight, startIndex); + } + const height = parseInt(hashOrHeight, 10); + const hash = await this.getBlockHashByHeight(height); + const txs = await this.getBlockTxsByHash(hash, startIndex); + return txs; + } + + protected async getBlockTxids(hashOrHeight: string): Promise { + if (hashOrHeight.startsWith('0')) { + const txs = await this.getBlockTxsByHash(hashOrHeight, 0); + return txs.map((tx) => tx.txid); + } + const height = parseInt(hashOrHeight, 10); + const hash = await this.getBlockHashByHeight(height); + const txids = await this.getBlockTxidsByHash(hash); + return txids; + } +} + diff --git a/backend/src/modules/bitcoin/block/dataloader/block-transactions.loader.ts b/backend/src/modules/bitcoin/block/dataloader/block-transactions.loader.ts new file mode 100644 index 00000000..e2391560 --- /dev/null +++ b/backend/src/modules/bitcoin/block/dataloader/block-transactions.loader.ts @@ -0,0 +1,48 @@ +import DataLoader from 'dataloader'; +import { Inject, Injectable, Logger } from '@nestjs/common'; +import { NestDataLoader } from '@applifting-io/nestjs-dataloader'; +import { DataLoaderResponse } from 'src/common/type/dataloader'; +import { BitcoinApiService } from 'src/core/bitcoin-api/bitcoin-api.service'; +import * as BitcoinApi from 'src/core/bitcoin-api/bitcoin-api.schema'; +import { CACHE_MANAGER, Cache } from '@nestjs/cache-manager'; +import { BitcoinBaseLoader } from './base'; + +export interface BitcoinBlockTransactionsLoaderParams { + hash?: string; + height?: number; + startIndex?: number; +} + +@Injectable() +export class BitcoinBlockTransactionsLoader + extends BitcoinBaseLoader + implements NestDataLoader +{ + protected logger = new Logger(BitcoinBlockTransactionsLoader.name); + + constructor( + public bitcoinApiService: BitcoinApiService, + @Inject(CACHE_MANAGER) public cacheManager: Cache, + ) { + super(); + } + + public getBatchFunction() { + return async (batchProps: BitcoinBlockTransactionsLoaderParams[]) => { + this.logger.debug(`Loading bitcoin block transactions`); + const results = await Promise.allSettled( + batchProps.map(async ({ hash, height, startIndex }) => + this.getBlockTxs(hash || height.toString(), startIndex), + ), + ); + return results.map((result) => (result.status === 'fulfilled' ? result.value : null)); + }; + } +} +export type BitcoinBlockTransactionsLoaderType = DataLoader< + BitcoinBlockTransactionsLoaderParams, + BitcoinApi.Transaction[] | null +>; +export type BitcoinBlockTransactionsLoaderResponse = + DataLoaderResponse; + diff --git a/backend/src/modules/bitcoin/block/dataloader/block-txids.loader.ts b/backend/src/modules/bitcoin/block/dataloader/block-txids.loader.ts new file mode 100644 index 00000000..fca98f37 --- /dev/null +++ b/backend/src/modules/bitcoin/block/dataloader/block-txids.loader.ts @@ -0,0 +1,39 @@ +import DataLoader from 'dataloader'; +import { Inject, Injectable, Logger } from '@nestjs/common'; +import { NestDataLoader } from '@applifting-io/nestjs-dataloader'; +import { DataLoaderResponse } from 'src/common/type/dataloader'; +import { BitcoinApiService } from 'src/core/bitcoin-api/bitcoin-api.service'; +import { CACHE_MANAGER, Cache } from '@nestjs/cache-manager'; +import { BitcoinBaseLoader } from './base'; + +export interface BitcoinBlockTxidsLoaderParams { + hash?: string; + height?: number; +} + +@Injectable() +export class BitcoinBlockTxidsLoader + extends BitcoinBaseLoader + implements NestDataLoader +{ + protected logger = new Logger(BitcoinBlockTxidsLoader.name); + + constructor( + public bitcoinApiService: BitcoinApiService, + @Inject(CACHE_MANAGER) public cacheManager: Cache, + ) { + super(); + } + + public getBatchFunction() { + return async (keys: BitcoinBlockTxidsLoaderParams[]) => { + this.logger.debug(`Loading bitcoin block transactions`); + const results = await Promise.allSettled( + keys.map(async ({ hash, height }) => this.getBlockTxids(hash || height.toString())), + ); + return results.map((result) => (result.status === 'fulfilled' ? result.value : null)); + }; + } +} +export type BitcoinBlockTxidsLoaderType = DataLoader; +export type BitcoinBlockTxidsLoaderResponse = DataLoaderResponse; diff --git a/backend/src/modules/bitcoin/block/dataloader/block.loader.ts b/backend/src/modules/bitcoin/block/dataloader/block.loader.ts new file mode 100644 index 00000000..d63d859c --- /dev/null +++ b/backend/src/modules/bitcoin/block/dataloader/block.loader.ts @@ -0,0 +1,34 @@ +import DataLoader from 'dataloader'; +import { Inject, Injectable, Logger } from '@nestjs/common'; +import { NestDataLoader } from '@applifting-io/nestjs-dataloader'; +import { DataLoaderResponse } from 'src/common/type/dataloader'; +import { BitcoinApiService } from 'src/core/bitcoin-api/bitcoin-api.service'; +import * as BitcoinApi from 'src/core/bitcoin-api/bitcoin-api.schema'; +import { CACHE_MANAGER, Cache } from '@nestjs/cache-manager'; +import { BitcoinBaseLoader } from './base'; + +@Injectable() +export class BitcoinBlockLoader + extends BitcoinBaseLoader + implements NestDataLoader +{ + protected logger = new Logger(BitcoinBlockLoader.name); + + constructor( + public bitcoinApiService: BitcoinApiService, + @Inject(CACHE_MANAGER) public cacheManager: Cache, + ) { + super(); + } + + public getBatchFunction() { + return async (keys: string[]) => { + this.logger.debug(`Loading bitcoin blocks: ${keys.join(', ')}`); + const results = await Promise.allSettled(keys.map(async (key) => this.getBlock(key))); + return results.map((result) => (result.status === 'fulfilled' ? result.value : null)); + }; + } +} +export type BitcoinBlockLoaderType = DataLoader; +export type BitcoinBlockLoaderResponse = DataLoaderResponse; + diff --git a/backend/src/modules/bitcoin/transaction/transaction.resolver.ts b/backend/src/modules/bitcoin/transaction/transaction.resolver.ts index f055e946..9c459f22 100644 --- a/backend/src/modules/bitcoin/transaction/transaction.resolver.ts +++ b/backend/src/modules/bitcoin/transaction/transaction.resolver.ts @@ -12,7 +12,7 @@ import { RgbppTransactionLoaderType, } from 'src/modules/rgbpp/transaction/transaction.dataloader'; import { BitcoinBaseBlock, BitcoinBlock } from '../block/block.model'; -import { BitcoinBlockLoader, BitcoinBlockLoaderType } from '../block/block.dataloader'; +import { BitcoinBlockLoader, BitcoinBlockLoaderType } from '../block/dataloader/block.loader'; @Resolver(() => BitcoinTransaction) export class BitcoinTransactionResolver { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 931821e4..05d7bb1d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -27,7 +27,7 @@ importers: version: 0.23.0 '@nestjs/cache-manager': specifier: ^2.2.2 - version: 2.2.2(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.10(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.10)(reflect-metadata@0.2.2)(rxjs@7.8.1))(cache-manager@5.7.1)(rxjs@7.8.1) + version: 2.2.2(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.10(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.10)(reflect-metadata@0.2.2)(rxjs@7.8.1))(cache-manager@5.7.4)(rxjs@7.8.1) '@nestjs/common': specifier: ^10.0.0 version: 10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1) @@ -74,8 +74,11 @@ importers: specifier: ^1.7.2 version: 1.7.2 cache-manager: - specifier: ^5.7.1 - version: 5.7.1 + specifier: ^5.2.3 + version: 5.7.4 + cache-manager-redis-yet: + specifier: ^4.1.2 + version: 4.2.0 dataloader: specifier: ^2.2.2 version: 2.2.2 @@ -94,6 +97,9 @@ importers: mercurius-cache: specifier: ^6.0.1 version: 6.0.1 + redis: + specifier: ^4.6.7 + version: 4.7.0 reflect-metadata: specifier: ^0.2.0 version: 0.2.2 @@ -2451,6 +2457,35 @@ packages: '@radix-ui/colors@3.0.0': resolution: {integrity: sha512-FUOsGBkHrYJwCSEtWRCIfQbZG7q1e6DgxCIOe1SUQzDe/7rXXeA47s8yCn6fuTNQAj1Zq4oTFi9Yjp3wzElcxg==} + '@redis/bloom@1.2.0': + resolution: {integrity: sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==} + peerDependencies: + '@redis/client': ^1.0.0 + + '@redis/client@1.6.0': + resolution: {integrity: sha512-aR0uffYI700OEEH4gYnitAnv3vzVGXCFvYfdpu/CJKvk4pHfLPEy/JSZyrpQ+15WhXe1yJRXLtfQ84s4mEXnPg==} + engines: {node: '>=14'} + + '@redis/graph@1.1.1': + resolution: {integrity: sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw==} + peerDependencies: + '@redis/client': ^1.0.0 + + '@redis/json@1.0.7': + resolution: {integrity: sha512-6UyXfjVaTBTJtKNG4/9Z8PSpKE6XgSyEb8iwaqDcy+uKrd/DGYHTWkUdnQDyzm727V7p21WUMhsqz5oy65kPcQ==} + peerDependencies: + '@redis/client': ^1.0.0 + + '@redis/search@1.2.0': + resolution: {integrity: sha512-tYoDBbtqOVigEDMAcTGsRlMycIIjwMCgD8eR2t0NANeQmgK/lvxNAvYyb6bZDD4frHRhIHkJu2TBRvB0ERkOmw==} + peerDependencies: + '@redis/client': ^1.0.0 + + '@redis/time-series@1.1.0': + resolution: {integrity: sha512-c1Q99M5ljsIuc4YdaCwfUEXsofakb9c8+Zse2qxTadu8TalLXuAESzLvFAvNVbkmSlvlzIQOLpBCmWI9wTOt+g==} + peerDependencies: + '@redis/client': ^1.0.0 + '@rgbpp-sdk/btc@0.0.0-snap-20240727021715': resolution: {integrity: sha512-G8NTqe8CTHEzykQonfTHNWzL8OcoDDyXo9tQpT64yRdLgxwLHgGelpfnfYfE0TvshgxDG9UN5Yi194At++c7MQ==} @@ -3738,8 +3773,12 @@ packages: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} - cache-manager@5.7.1: - resolution: {integrity: sha512-dONlk3HCRelyxH9ctcXBgFihKmtSdudc9H0E39pBQeUaNcBJV3vcmcvifRUGqbeKk+uWCQpAts3uvnj+79Ebrg==} + cache-manager-redis-yet@4.2.0: + resolution: {integrity: sha512-3Exp8Hv52G/K8oY5U8OwS2A7MJEJmNUvn9DPEnNSo/yu+Ken4v9VEnIAq9YZ6b6E0LN1NwPXNF3N+IaQM9RcTQ==} + engines: {node: '>= 16.17.0'} + + cache-manager@5.7.4: + resolution: {integrity: sha512-7B29xK1D8hOVdrP0SAy2DGJ/QZxy2TqxS8s2drlLGYI/xOTSJmXfatks7aKKNHvXN6SnKnPtYCi0T82lslB3Fw==} engines: {node: '>= 18'} call-bind@1.0.7: @@ -3864,6 +3903,10 @@ packages: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} + cluster-key-slot@1.1.2: + resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} + engines: {node: '>=0.10.0'} + co@4.6.0: resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} @@ -4767,6 +4810,10 @@ packages: generate-function@2.3.1: resolution: {integrity: sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==} + generic-pool@3.9.0: + resolution: {integrity: sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==} + engines: {node: '>= 4'} + gensequence@7.0.0: resolution: {integrity: sha512-47Frx13aZh01afHJTB3zTtKIlFI6vWY+MYCN9Qpew6i52rfKjnhCF/l1YlC8UmEMvvntZZ6z4PiCcmyuedR2aQ==} engines: {node: '>=18'} @@ -6384,6 +6431,9 @@ packages: resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} engines: {node: '>= 12.13.0'} + redis@4.7.0: + resolution: {integrity: sha512-zvmkHEAdGMn+hMRXuMBtu4Vo5P6rHQjLoHftu+lBqq8ZTA3RCVC/WzD790bkKKiNFp7d5/9PcSD19fJyyRvOdQ==} + reflect-metadata@0.2.2: resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} @@ -7354,6 +7404,9 @@ packages: yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + yaml@1.10.2: resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} engines: {node: '>= 6'} @@ -9483,11 +9536,11 @@ snapshots: '@nervosnetwork/ckb-types@0.109.2': {} - '@nestjs/cache-manager@2.2.2(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.10(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.10)(reflect-metadata@0.2.2)(rxjs@7.8.1))(cache-manager@5.7.1)(rxjs@7.8.1)': + '@nestjs/cache-manager@2.2.2(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.10(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.10)(reflect-metadata@0.2.2)(rxjs@7.8.1))(cache-manager@5.7.4)(rxjs@7.8.1)': dependencies: '@nestjs/common': 10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1) '@nestjs/core': 10.3.10(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.10)(reflect-metadata@0.2.2)(rxjs@7.8.1) - cache-manager: 5.7.1 + cache-manager: 5.7.4 rxjs: 7.8.1 '@nestjs/cli@10.4.2': @@ -10164,6 +10217,32 @@ snapshots: '@radix-ui/colors@3.0.0': {} + '@redis/bloom@1.2.0(@redis/client@1.6.0)': + dependencies: + '@redis/client': 1.6.0 + + '@redis/client@1.6.0': + dependencies: + cluster-key-slot: 1.1.2 + generic-pool: 3.9.0 + yallist: 4.0.0 + + '@redis/graph@1.1.1(@redis/client@1.6.0)': + dependencies: + '@redis/client': 1.6.0 + + '@redis/json@1.0.7(@redis/client@1.6.0)': + dependencies: + '@redis/client': 1.6.0 + + '@redis/search@1.2.0(@redis/client@1.6.0)': + dependencies: + '@redis/client': 1.6.0 + + '@redis/time-series@1.1.0(@redis/client@1.6.0)': + dependencies: + '@redis/client': 1.6.0 + '@rgbpp-sdk/btc@0.0.0-snap-20240727021715(@ckb-lumos/lumos@0.23.0)': dependencies: '@bitcoinerlab/secp256k1': 1.1.1 @@ -12286,7 +12365,18 @@ snapshots: cac@6.7.14: {} - cache-manager@5.7.1: + cache-manager-redis-yet@4.2.0: + dependencies: + '@redis/bloom': 1.2.0(@redis/client@1.6.0) + '@redis/client': 1.6.0 + '@redis/graph': 1.1.1(@redis/client@1.6.0) + '@redis/json': 1.0.7(@redis/client@1.6.0) + '@redis/search': 1.2.0(@redis/client@1.6.0) + '@redis/time-series': 1.1.0(@redis/client@1.6.0) + cache-manager: 5.7.4 + redis: 4.7.0 + + cache-manager@5.7.4: dependencies: eventemitter3: 5.0.1 lodash.clonedeep: 4.5.0 @@ -12433,6 +12523,8 @@ snapshots: clone@1.0.4: {} + cluster-key-slot@1.1.2: {} + co@4.6.0: {} code-block-writer@12.0.0: {} @@ -13671,6 +13763,8 @@ snapshots: dependencies: is-property: 1.0.2 + generic-pool@3.9.0: {} + gensequence@7.0.0: {} gensync@1.0.0-beta.2: {} @@ -15438,6 +15532,15 @@ snapshots: real-require@0.2.0: {} + redis@4.7.0: + dependencies: + '@redis/bloom': 1.2.0(@redis/client@1.6.0) + '@redis/client': 1.6.0 + '@redis/graph': 1.1.1(@redis/client@1.6.0) + '@redis/json': 1.0.7(@redis/client@1.6.0) + '@redis/search': 1.2.0(@redis/client@1.6.0) + '@redis/time-series': 1.1.0(@redis/client@1.6.0) + reflect-metadata@0.2.2: {} reflect.getprototypeof@1.0.6: @@ -16437,6 +16540,8 @@ snapshots: yallist@3.1.1: {} + yallist@4.0.0: {} + yaml@1.10.2: {} yaml@2.4.5: {}